参考文章:关于hibernate的缓存使用
这篇博文已经说的很详细,不过我这里还有一些补充说明的。
——————————————————————————————————————————————
Hibernate持久层缓存的级别:
(1)事务级别
该级别缓存中的缓存对象只能被当前事务使用,每个事务都有各自的缓存,缓存中的数据通常以关联对象的形式保存。同时被缓存对象的生命周期依赖于当前事务的生命周期,当前事务结束时,该缓存中缓存对象的生命周期也会结束。事务级别的缓存通常使用内存作为保存缓存对象的存储介质,Hibernate的一级缓存(Session缓存)即该级别的缓存。
(2)应用(进程)级别
该级别缓存中对象可以被当前应用(进程)内的所有事务共享访问,被缓存对象的生命周期与当前应用相同。当应用结束时,缓存对象的生命周期结束。如果当前应用是一个分布式应用,则不能使用该级别的缓存,这种级别的缓存使用内存或硬盘作为缓存对象的存储介质。
(3)分布式级别
如果当前应用部署在多台服务器的分布式(集群)环境下,则当前应用可以使用分布式级别的缓存缓存持久化对象。分布式缓存中缓存的数据会被一台或者多台服务器共享。如果缓存数据发生变化,则更新后的缓存数据会同步到集群中的每台服务器中,进而保证缓存数据的一致性。
Hibernate的二级缓存可以是应用级别或者分布式级别的缓存,完全依赖于第三方缓存组件的具体实现。
——————————————————————————————————————————————
Hibernate没有提供自身产品级别的二级缓存,而是在设计上利用第三方成熟的缓存组件实现。为了集成不同的第三方缓存组件
Hibernate提供了org.hibernate.cache.CacheProvider接口用来作为缓存组件与Hibernate之间的适配器。在实际开发中,
Hibernate二级缓存组件如表:
缓存名称 |
对应的适配器类 |
Hashtable |
org.hibernate.cache.HashtableCacheProvider |
EHCache |
org.hibernate.cache.EhCacheProvider |
OSCache |
org.hibernate.cache.OSCacheProvider |
SwarmCache |
org.hibernate.cache.SwarmCacheProvider |
JBoss Cache 1.x |
org.hibernate.cache.TreeCacheProvider |
Jboss Cache 2 |
org.hibernate.cache.jbc2.JBossCacheRegionFactory |
———————————————————————————————————————————————
二级缓存的策略:
(1)只读策略(read-only)
只读缓存是最简单而且高效的缓存策略,缓存的只是只读对象,不能修改。如果Hibernate应用中的持久化对象或者集合对象只需要读取,不需要修改,则可为其设置改策略。
(2)读/写策略(read-write)
读/写策略适合缓存对象既要读取,又要更新修改的Hibernate应用。如果使用Serializable级别的事务隔离级别,则不能使用这种缓存策略。如果在分布式应用中使用这种策略,则需要底层的缓存组件支持锁定机制。
(3)同严格的读/写策略(nonstrict-read-write)
不严格的读/写策略适合被缓存对象读取频繁且极少更新的Hibernate应用,它不保证两个事务并发修改同一个缓存数据的一致性,在性能上要比读写缓存策略高。
(4)事务缓存(transactional)
事务缓存策略提供对缓存数据的全面支持,只能用于JTA环境中。
———————————————————————————————————————————————
应用EHCache作为二级缓存:
项目框架:
编写hibernate.cfg.xml:
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <!-- 声明二级缓存的组件类型 --> <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property> <!-- <property name="hibernate.cache.use_query_cache">true</property> --> <property name="show_sql">true</property> <property name="current_session_context_class">thread</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.url">jdbc:mysql://localhost:3306/book</property> <property name="connection.username">******</property> <property name="connection.password">******</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <mapping resource="com/sunflower/entity/Student.hbm.xml" /> </session-factory> </hibernate-configuration>
编写ehcache.xml文件:
1 <ehcache> 2 <diskStore path="c:/cachetest" /> 3 <defaultCache maxElementsInMemory="4" eternal="false" 4 timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> 5 6 <cache name="com.sunflower.entity.Student" maxElementsInMemory="4" eternal="false" 7 timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> 8 </ehcache>
编写Student.hbm.xml文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping> 7 <class name="com.sunflower.entity.Student" table="student"> 8 <!-- 为持久化类设置二级缓存 --> 9 <cache usage="read-only"/> 10 11 <id name="id" type="string" column="student_id"> 12 <generator class="uuid"></generator> 13 </id> 14 15 <property name="name" type="string" column="name"></property> 16 <property name="age" type="integer" column="age"></property> 17 <property name="address" type="string" column="address"></property> 18 </class> 19 </hibernate-mapping>
编写测试类:Test.java:
1 package com.sunflower.test; 2 3 import java.util.List; 4 5 import org.hibernate.CacheMode; 6 import org.hibernate.Query; 7 import org.hibernate.Session; 8 import org.hibernate.Transaction; 9 10 import com.sunflower.entity.Student; 11 import com.sunflower.util.HibernateUtil; 12 13 /** 14 * @author Caihanyuan 15 * @time 2012-9-1 上午11:13:57 16 */ 17 public class Test { 18 public static void main(String[] args) { 19 Session session = HibernateUtil.getSession(); 20 Session session2 = HibernateUtil.getSession(); 21 22 Transaction ts = session.beginTransaction(); 23 Transaction ts2 = session2.beginTransaction(); 24 25 try { 26 // HibernateUtil.getFactory().evict(Student.class); 27 // 28 // for (int i = 1; i <= 10; i++) { 29 // Student student = new Student(); 30 // student.setName("Student" + i); 31 // 32 // session.save(student); 33 // } 34 35 // Query query = session.createQuery("from Student"); 36 // query.setCacheable(true); 37 // List<Student> list = query.list(); 38 // System.out.println("---------------------------------------------------------"); 39 // 40 // query = session.createQuery("from Student"); 41 // query.setCacheable(true); 42 // list = query.list(); 43 44 Student student1 = (Student) session.load(Student.class, 45 "8a85f4eb3980c13a013980c13b490002"); 46 System.out.println("student1 name:" + student1.getName()); 47 48 Student student2 = (Student) session2.load(Student.class, 49 "8a85f4eb3980c13a013980c13b490002"); 50 System.out.println("student2 name:" + student2.getName()); 51 52 ts.commit(); 53 ts2.commit(); 54 } 55 catch (Exception e) { 56 if (null != ts && ts.isActive()) 57 ts.rollback(); 58 if (null != ts2 && ts2.isActive()) 59 ts2.rollback(); 60 e.printStackTrace(); 61 } 62 finally { 63 HibernateUtil.closeSession(session); 64 HibernateUtil.closeSession(session2); 65 } 66 } 67 }
程序输出结果:
Hibernate: select student0_.student_id as student1_0_0_, student0_.name as name0_0_, student0_.age as age0_0_, student0_.address as address0_0_ from student student0_ where student0_.student_id=?
student1 name:Student2
student2 name:Student2
两个session只查询了一次数据库,可知调用了二级缓存