Session的缓存是内置的,不能被卸载,也被称为Hibernate的第一级缓存。此外,SessionFactory有一个内置缓存和一个外置缓存,其中外置缓存是可插拔的缓存插件,也被称为Hibernate的第二级缓存。第二级缓存本身的实现很复杂,必须实现并发访问策略以及数据过期策略等。
持久化层的缓存的范围
1.事务范围:一级缓存
2.进程范围:二级缓存
3.群集范围:二级缓存
在同一事务的缓存中,持久化类的每个对象具有唯一的OID,例如不会出现两个OID都为1的Customer对象。
但在进程范围和群集范围的缓存的数据采用对象的散装数据形式。也就是说每个事务都会获得不同的Customer对象。
如果二级缓存中存放的数据会经常被事务修改,就不得不提高缓存的事务隔离级别,但是这又会降低并发性能。因此,只有符合以下条件的数据才适合存放到第二级缓存中:
1.很少被修改的数据
2.不是很重要的数据,允许出现偶尔的并发问题。
3.不会被并发访问的数据。
4.参考数据(供应用参考的常量数据)
以下数据不适合存放到第二级缓存中:
1.经常被修改的数据
2.财务数据,绝对不允许出现并发问题。
3.与其他应用共享的数据。因为当时当使用了第二级缓存的Hibernate应用与其他应用共享数据库中的某种数据时,如果其他应用修改了数据库中的数据,Hibernate无法自动保证第二级缓存中的数据与数据库保持一致。
当应用程序调用Session的save update saveOrUpdate load get find以及调用查询接口的list iterate filter方法时,如果在session的缓存中还不存在相应的对象, Hibernate就会把该对象加入到第一级缓存中。当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。
直接通过Hibernate API进行批量更新和批量删除都不值得推荐。而直接通过JDBC API执行相关的SQL语句或调用相关的存储过程,是批量更新和批量删除的最佳方式,这两种方式都有以下优点:
1.无需把数据库中大量批量数据先加载到内存中,然后逐个更新或修改它们,因此不会消耗大量内存。
2.能在一掉sql语句中更新或删除大批量的数据
配置第二级缓存主要包含以下步骤:
1.选择需要使用第二级缓存的持久化类,设置它的命名缓存的并发访问策略。
2.选择合适的缓存插件,每一个缓存插件都有自带的配置文件,因此需要手工编辑该配置文件。
HIbernate的缓存介于Hibernate应用和数据库之间,缓存中存放了数据库的数据的拷贝。缓存主要用来减少直接访问数据库的频率,从而提高应用的性能。Hibernate采用二级缓存机制,如果在第一集缓存中没有查询到想用的数据,还可以到第二级缓存内查询,如果在第二级缓存内也没有找到该数据,那么就只好查询数据库。第一级缓存是session的缓存,第二级缓存是sessionFactory的外置缓存。
二级缓存除了以内存作为存储介质外,还可以选用硬盘等外部存储设备
Hibernate的二级缓存策略的一般过程如下:
1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。
2) 把获得的所有数据对象根据ID放入到第二级缓存中。
3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
4) 删除、更新、增加数据的时候,同时更新缓存。
Hibernate的二级缓存策略,是针对于ID查询的缓存策略(例如:使用load()方法查询),对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query缓存。使用查询缓存功能,需要让两次查询所对应的HQL语句相同,同时这两次查询之间表中的数据没有任何变动。
激活使用二级缓存后方可使用Hibernate的查询缓存的功能。
Hibernate的Query缓存策略的过程如下:
1) Hibernate首先根据这些信息组成一个Query Key,Query Key包括条件查询的请求一般信息:SQL, SQL需要的参数,记录范围(起始位置rowStart,最大记录个数maxRows),等。保证同样查询下有相同的key值。如果该HQL查询返回一个List对象,Key值对应的Value值为List中各个元素的标示符属相(id)的集合;如果HQL查询中包含select字句,则为所有查询到的数据。
2) Hibernate根据这个Query Key到Query缓存中查找对应的结果列表。如果存在,那么返回这个结果列表;如果不存在,查询数据库,获取结果列表,把整个结果列表根据Query Key放入到Query缓存中。
3) Query Key中的SQL涉及到一些表名,如果这些表的任何数据发生修改、删除、增加等操作,这些相关的Query Key都要从缓存中清空。