上篇博客介绍了Hibernate的基本原理,在博客尾声的时候提到了Hibernate的缓存机制以及延迟加载问题,这篇博客我们继续,将这两部分的内容补充完。
首先说说Hibernate的缓存机制,我们都知道Hiernate有一级缓存、二级缓存,但是具体的机制原理了解的清楚吗?这里我们就来好好说说Hibernate的缓存机制。先说说为什么要用缓存机制?Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对数据源访问的频次,从而提高应用程度的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存中读写数据,在特定时间或事件中的会同步缓存和物理数据源的数据。
介绍完Hibernate缓存的作用,下面说说Hibernate缓存的分类了其实我们上面都说了,Hibernate缓存分为一级缓存和二级缓存。Hibernate的一级缓存 又称为“Session的缓存”,它是内置的,不能被卸载,这里面的不能卸载的意识是这种缓存不具有可选性,是必须有的功能,是不能被取消的。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围内的缓存。一级缓存是必须的,不允许而且事实上也无法卸除。在一级缓存中,持久化类的每一个实例都具有唯一的OID。下面说二级缓存,Hibernate的二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate的二级缓存是进程范围或者集群范围的缓存。有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别,二级缓存是可选的,相对于一级缓存而言它是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。
那么什么样的数据适合存在二级缓存中呢?第一、很少被修改的数据;第二、不是很重要的数据,允许出现偶尔并发的数据;第三、不会被并发访问的数据;第四、常量的数据。那么相对而言什么样的数据不适合存放在二级缓存中呢?第一、经常被修改的数据;第二、绝对不允许出现并发访问的数据,如财务数据;第三、与其他应用程序共享的数据。
那么具体是如何应用缓存机制的呢?我们来举个例子,比如说当Hibernate根据ID访问数据对象的时候,它会首先从Session一级缓存中去查,如果查不到,如果配置了二级缓存,就去二级缓存中去查;如果还查不到,那么就去数据库中查,把结果按照ID放入到缓存中。删除、更新、增加数据的时候,同时更新缓存。
好了,Hibernate的缓存机制就介绍了到这里,下面我们说说Hibernate的延迟加载。Hibernate的延迟加载是非常常用的技术。先说延迟加载的概念,延迟加载时只有真正使用该对象时才会创建,对于Hibernate而言,它是支持延迟加载的,也称为懒加载,是在真正使用对象的时候才会发送sql语句,查询对象的时候不会发送sql语句。Hibernate通过这种延迟加载开降低系统的内存开销,从而保证Hibernate的运行性能。
Hibernate主要听过代理Proxy机制来实现延迟加载,具体的过程是Hibernate从数据库中获取某一个对象数据或某一个对象的集合属性值或获取某一个对象所关联的另一个对象时,由于没有使用该对象的数据,Hibernate并不是从数据库加载真正的数据,而只是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都是默认值。只有在真正需要使用该对象的数据时才创建这个真实对象,真正从数据库中加载它的数据,这样在某些情况下,可以提高查询效率。
get方法不支持延迟加载,get方法在查询不到对象时不会出现异常。与之对应的load方法支持延迟加载,load在查询不到对象时会抛出异常。举个例子说明一下,现在我们都知道了Hibernate的延迟加载会降低系统的内存开销,在某些程度上却是会给程序的查询效率带来好处,但有时候明确知道数据需要立刻被加载,如果Hibernate先默认使用延迟加载,随后又必须去数据库加载,反而会降低效率。这个时候怎么办?记住上面说的,get方法是不支持延迟加载的,如果在加载单个实体时,如果不需要延迟加载,就可以使用session的get()方法。提到session又想到了,Hibernate支持延迟加载必须在session开启的情况下才有效。
对Hibernate的延迟加载的基本介绍先到这里,研究的还不是特别深入,在以后的应用中会慢慢更新这方面的文章。个人觉得缓存机制和延迟加载是Hibernate中比较重要的知识点,需要很好的掌握。其实深挖东西是挺多的,欢迎大家提宝贵意见,欢迎留言我们一起沟通交流。