Hibernate的缓存包括Session的缓存和SessionFactory的缓存,其中SessionFactory的缓存又可以分为两类:内置缓存和外置缓存。Session的缓存是内置的,不能被卸载,也被称为Hibernate的第一级缓存。SessionFactory的内置缓存和Session的缓存在实现方式上比较相似,前者是SessionFactory对象的一些集合属性包含的数据,后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来,SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的第二级缓存。
简单理解一级缓存和二级缓存
一级缓存是Session级别的缓存,在Session关闭时,一级缓存就会失效。
第二级缓存是一个可插拔的的缓存插件,它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此第二级缓存是进程范围或者集群范围的缓存。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的,可以在每个类或每个集合的粒度上配置第二级缓存,如EhCache 、JBossCache、OsCache等。
二级缓存应用场景如下:
1)很少被修改的数据 2)不是很重要的数据,允许出现偶尔并发的数据 3)不会被并发访问的数据 4)参考数据
1、在 Hibernate 配置文件中增加如下内容:
<!-- 开启二级缓存 --> <property name="hibernate.cache.use_second_level_cache">true</property> <!-- 指定缓存产品提供商 --> <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property> <!-- 启用查询缓存 --> <property name="hibernate.cache.use_query_cache">true</property>
2、在 Entity 实体的java类上增加缓存注释(由hibernate扩展提供) :
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
缓存 CacheConcurrencyStrategy 方式有五种缓存方式:
CacheConcurrencyStrategy.NONE,不适用,默认 CacheConcurrencyStrategy.READ_ONLY ,只读模式,在此模式下,如果对数据进行更新操作,会有异常; CacheConcurrencyStrategy.READ_WRITE ,读写模式在更新缓存的时候会把缓存里面的数据换成一个锁,其它事务如果去取相应的缓存数据,发现被锁了,直接就去数据库查询; CacheConcurrencyStrategy.NONSTRICT_READ_WRITE ,不严格的读写模式则不会的缓存数据加锁; CacheConcurrencyStrategy.TRANSACTIONAL ,事务模式指缓存支持事务,当事务回滚时,缓存也能回滚,只支持 JTA 环境。
3、查询缓存需要在Query的方法执行前增加如下内容:
query.setCacheable(true);
使用Hibernate时获得query有 setCacheable 方法设置缓存,如果使用JPA时,javax.persistence.Query没有setCacheable方法可以进行转化再调用setCacheable方法,具体代码如下:
if (query instanceof org.hibernate.ejb.QueryImpl) { ((org.hibernate.ejb.QueryImpl) query).getHibernateQuery().setCacheable(true); }