什么样的数据适合存放到第二级缓存中?
l 很少被修改的数据
l 不是很重要的数据,允许出现偶尔并发的数据
l 不会被并发访问的数据
l 参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。
Hibernater 的二级缓存是一个插件,下面是几种常用的缓存插件:
l EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
l OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
l SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。
l JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。
配置二级缓存的主要步骤:
1) 选择需要使用二级缓存的持久化类,设置它的命名缓存的并发访问策略。这是最值得认真考虑的步骤。
2) 选择合适的缓存插件,然后编辑该插件的配置文件。
配置EhCache二级缓存:
1) 将echcache.xml文件拷贝到src下,这个文件在HIBERNATE_HOME/etc/
2) 开启二级缓存,修改hibernate.cfg.xml文件
添加<property name="hibernate.cache.use_second_level_cache">true</property>
不用添加也可以,因为hibernate默认开启二级缓存
3) 指定缓存产品提供商,修改hibernate.cfg.xml文件
添加
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
4) 指定那些实体类使用二级缓存(两种方法)
u 在映射文件中采用<cache>标签
u 在hibernate.cfg.xml文件中,采用<class-cache>标签
例子代码如下:
hibernate.cfg.xml: <hibernate-configuration> <session-factory> <property name="hibernate.connection.url"> jdbc:mysql://localhost/hibernate </property> <property name="hibernate.connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="hibernate.connection.username"> root </property> <property name="hibernate.connection.password"> root </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="hibernate/Classes.hbm.xml" /> <mapping resource="hibernate/Student.hbm.xml" />
<!-- 指定哪些对象,需要使用二级缓存 --> <class-cache class="hibernate.Student" usage="read-only" /> </session-factory> </hibernate-configuration> 测试代码: public class CacheLevel2Test extends TestCase { /** * 开启两个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); } }
/** * 开启两个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); } }
/** * 一级缓存和二级缓存的交互 */ 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); }
} } |