hibernate二级缓存
二级缓存也称进程级的缓存或SessionFactory级的缓存,二级缓存可以被所有的session共享。二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存
一、二级缓存的配置和使用:
1、 将hibernate-3.2\etc\echcache.xml文件拷贝到src下
2、开启二级缓存,修改hibernate.cfg.xml文件
<property name="hibernate.cache.use_second_level_cache">true</property>
3、指定缓存产品提供商,修改hibernate.cfg.xml文件
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
4、指定那些实体类使用二级缓存(两种方法)
在映射文件中采用<cache>标签
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.ncepu.hibernate.Student" table="t_student"> <cache usage="read-only"/> <id name="id"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="classes" column="classesid"/> </class> </hibernate-mapping>
或在hibernate.cfg.xml文件中,采用<class-cache>标签
<class-cache class="com.ncepu.hibernate.Student" usage="read-only"/>
最终的hibernate.cfg.xml文件
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_cache</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">ncepu</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.show_sql">true</property> <!-- 开启二级缓存 --> <property name="hibernate.cache.use_second_level_cache">true</property> <!-- 指定缓存产品提供商 --> <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> <mapping resource="com/ncepu/hibernate/Student.hbm.xml"/> <class-cache class="com.ncepu.hibernate.Student" usage="read-only"/> </session-factory> </hibernate-configuration>
二、echcache.xml说明
1、echcache.xml中
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />
The following attributes are required for defaultCache:
name - Sets the name of the cache. This is used to identify the cache. It must be unique.
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used . if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used.if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit.
三、Test
1、二级缓存是缓存实体对象的,get()、load() 等方法都会使用。
/** * 开启两个session,分别调用load */ public void testCache1() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); Student student = (Student)session.load(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } try { session = HibernateUtils.getSession(); session.beginTransaction(); //不会发出sql,因为开启了二级缓存,session是共享二级缓存的 Student student = (Student)session.load(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } /** * 开启两个session,分别调用get */ public void testCache2() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); Student student = (Student)session.get(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } try { session = HibernateUtils.getSession(); session.beginTransaction(); //不会发出sql,因为开启了二级缓存,session是共享二级缓存的 Student student = (Student)session.get(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
2、sessionFactory管理二级缓存
factory.evict(Student.class, 1);
factory.evict(Student.class);
/** * 开启两个session,分别调用load,在使用SessionFactory清除二级缓存 */ public void testCache3() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); Student student = (Student)session.load(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } //管理二级缓存 SessionFactory factory = HibernateUtils.getSessionFactory(); //factory.evict(Student.class); factory.evict(Student.class, 1); try { session = HibernateUtils.getSession(); session.beginTransaction(); //会发出查询sql,因为二级缓存中的数据被清除了 Student student = (Student)session.load(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
3、一级缓存和二级缓存的交互 (了解即可)
/** * 一级缓存和二级缓存的交互 */ public void testCache4() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); //仅向二级缓存读数据,而不向二级缓存写数据 session.setCacheMode(CacheMode.GET); Student student = (Student)session.load(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } try { session = HibernateUtils.getSession(); session.beginTransaction(); //发出sql语句,因为session设置了CacheMode为GET,所以二级缓存中没有数据 Student student = (Student)session.load(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } try { session = HibernateUtils.getSession(); session.beginTransaction(); //只向二级缓存写数据,而不从二级缓存读数据 session.setCacheMode(CacheMode.PUT); //会发出查询sql,因为session将CacheMode设置成了PUT Student student = (Student)session.load(Student.class, 1); System.out.println("student.name=" + student.getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
CacheMode参数用于控制具体的Session如何与二级缓存进行交互。
CacheMode.NORMAL - 从二级缓存中读、写数据。
CacheMode.GET - 从二级缓存中读取数据,仅在数据更新时对二级缓存写数据。
CacheMode.PUT - 仅向二级缓存写数据,但不从二级缓存中读数据。
CacheMode.REFRESH - 仅向二级缓存写数据,但不从二级缓存中读数据。