三种算法:
NRU--最近不适用
FIFO--先进先出
LRU--最近最少使用
一级缓存
* session级别的缓存(事务级缓存),即session关闭,缓存关闭
* 只缓存实体对象,不缓存普通属性
Method Read Write Comments session.load() Y Y session.get() Y Y query.iterate() 查询实体 Y Y query.iterate() 查询普通属性 N N session.evict() NA NA 可以清理session session.clear() NA NA 可以清理session query.list() N Y 查询对象和普通属性都不会使用缓存
默认情况下:
list()会写缓存,但是不读取缓存,不会出现n+1问题
iterator()对缓存有读和写,但是在使用的时候,可能会出现 n+1 问题
ps:Oracle的Sql load支持大数据量的sql
二级缓存
SessionFactory级缓存(进程级缓存),可以被所有的session共享,生命周期与Sessionfactory一致,SessionFacotry可以管理二级缓存
一般采用第三方的缓存产品,例如:EhCache,Hibernate对于二级缓存的支持,可以参见Hibernate的手册
该示例为采用ehcache:
1.copy ${HIBERNATE_MENU}/project/etc/ehcache.xml 至 src下,下载ehcache-x.x.jar和commons-logging-1.1.1.jar
ehcache.xml中可以可以自定义2级缓存的使用策略
2.配置hibernate.cfg.xml
a. 显示开起Hibernate的二级缓存,默认为开启
<property name="hibernate.cache.use_seconde_level_cache">true</property> <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
b. 指定使用二级缓存的实体类,可以在Student.hbm.xml配置,也可以在Hibernate.cfg.xml中配置,推荐第二种做法,需要写在<mapping>后边
<class-cache usage="read-only" class="com.lohamce.hibernate.Classes"/>
PS:缓存的提供商,replication(修改),invalidation(删除,使用到的时候再加载)
Cache Provider class Type Cluster Safe Query Cache Supported Hashtable (not intended for production use) org.hibernate.cache.HashtableCacheProvider
memory yes EHCache org.hibernate.cache.EhCacheProvider
memory, disk yes OSCache org.hibernate.cache.OSCacheProvider
memory, disk yes SwarmCache org.hibernate.cache.SwarmCacheProvider
clustered (ip multicast) yes (clustered invalidation) JBoss Cache 1.x org.hibernate.cache.TreeCacheProvider
clustered (ip multicast), transactional yes (replication) yes (clock sync req.) JBoss Cache 2 org.hibernate.cache.jbc.JBossCacheRegionFactory
clustered (ip multicast), transactional yes (replication or invalidation) yes (clock sync req.)
3. 测试代码
@Test public void testManageCache1() { Session session = null; Transaction tx = null; try { session = HibernateUtil.openSession(); tx = session.beginTransaction(); Student s = (Student)session.get(Student.class, 1); s.setName("Scott"); System.out.println(s.getName()); tx.commit(); } catch (Exception e) { e.printStackTrace(); if (tx != null) tx.rollback(); } finally { HibernateUtil.close(session); } // 驱除二级缓存中的实体对象 SessionFactory factory = HibernateUtil.getSessionfactory(); factory.getCache().evictEntity(Student.class, 1); try { session = HibernateUtil.openSession(); tx = session.beginTransaction(); Student s = (Student)session.get(Student.class, 1); System.out.println(s.getName()); tx.commit(); } catch (Exception e) { e.printStackTrace(); if (tx != null) tx.rollback(); } finally { HibernateUtil.close(session); } }
session = HibernateUtil.openSession(); tx = session.beginTransaction(); // 此处可以设置缓存模式,Get为只读,详情参考文档 session.setCacheMode(CacheMode.GET); Student s = (Student)session.get(Student.class, 1); s.setName("Scott"); System.out.println(s.getName()); tx.commit();
查询缓存(使用得不多)
缓存的对象:针对普通属性的结果集的缓存,对实体对象的结果集只缓存Id
生命周期:缓存表数据修改,则缓存就失效,跨session
hibernate.cfg.xml中需要配置
<property name="hibernate.cache.use_query_cache">true</property>
代码: query.setCacheable(true);
且只对query.list()起作用,对query.iterate()不起作用.