Hibernate的二级缓存

Hibernate二级缓存:
二级缓存也称位进程级缓存或者sessionFactory级缓存,二级缓存可以被所有的session共享

二级缓存的配置和使用:
*将echcache.xml(这个文件在hibernate代码包中的etc 目录下)拷贝到src目录下
*开启二级缓存 修改hibernate.cfg.xml文件
<property name="hibernate.cache.use_second_level_cache">true</property>
*指定缓存产品提供商,修改hibernate.cfg.xml文件
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
*指定哪些类使用二级缓存:
* 在映射文件中采用<cache usage=""> 标签
* 在hibernate.cfg.xml中配置
<class-cache class="com.june.hibernate.Student" usage="read-only"/>
我推荐优先使用<read-only>
1. <read-only>
如果你的应用程序只需读取一个持久化类的实例,而无需对其修改, 那么就可以对其进行只读 缓存。这是最简单,也是实用性最好的方法。
甚至在集群中,它也能完美地运作。
2. read/write
如果应用程序需要更新数据,那么使用读/写缓存 比较合适。 如果应用程序要求“序列化事务”的隔离级别(serializable transaction
isolation level), 那么就决不能使用这种缓存策略。如果在JTA环境中使用缓存,你必须指定hibernate.transaction.manager_lookup_
class属性的值, 通过它,Hibernate才能知道该应用程序中JTA的TransactionManager的具体策略。 在其它环境中,你必须保证在Session.close()
、或Session.disconnect()调用前, 整个事务已经结束。 如果你想在集群环境中使用此策略,你必须保证底层的缓存实现支持锁定(locking)。Hibernate
内置的缓存策略并不支持锁定功能
3. nonstrict read/write
如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离, 那么比较适合使用非严格读/写
缓存策略。如果在JTA环境中使用该策略, 你必须为其指定hibernate.transaction.manager_lookup_class属性的值, 在其它环境中,你必须保证在
Session.close()、或Session.disconnect()调用前, 整个事务已经结束


二级缓存的是缓存实体对象的:
了解一级缓存的交互(session.setCacheMode())
主要是 CacheMode.NORMAL
CacheMode.PUT
CacheMode.GET
具体常见HibernateReference
有如下2个类 :

public class Clazz {
private Integer id;
private String name;
private Set<Student> students=new HashSet<Student>();
}
public class Student {
private Integer id;
private String name;
private Clazz clazz;
}


映射文件为(我们对students类设置缓存):

<class name="com.june.hibernate.Clazz" table="t_clazz">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="students" inverse="true">
<key column="clazz"/>
<one-to-many class="com.june.hibernate.Student"/>
</set>
</class>
<class name="com.june.hibernate.Student" table="t_student">
<!--
<cache usage="read-only"/>-->
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<many-to-one name="clazz" cascade="save-update"></many-to-one>
</class>

Hibernate 配置文件:

<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_cache_level_2</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<!-- 开启二级缓存 hibernate默认就是开启的 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 指定缓存产品提供商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<mapping resource="com/june/hibernate/Clazz.hbm.xml"/>
<mapping resource="com/june/hibernate/Student.hbm.xml"/>
<!-- 我推荐在此设置二级缓存 而不是在具体的类配置文件中设置 因为在此设置会对非常清楚的了解 那些是设了二级缓存的 那些是没有设的-->
<class-cache class="com.june.hibernate.Student" usage="read-only"/>
</session-factory>
</hibernate-configuration>


测试用例:

package com.june.hibernate;

import junit.framework.TestCase;

import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class CacheLevel2Test extends TestCase{
/**
* 开启2个session分别调用load
*/
public void testLoad(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}

try{
//第二个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
//不会发出session 因为开启了二级缓存 session共享二级缓存
// load()方法也使用二级缓存
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
/**
* 开启2个session分别调用get()
*/
public void testGet(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.get(Student.class,1);
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}

try{
//第二个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.get(Student.class,1);
//也不会发出session 因为开启了二级缓存 session共享二级缓存
//get()也使用二级缓存
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
/**
* 开启2个session分别调用load 用sessionFactory 清除二级缓存
*/
public void testLoad2(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
SessionFactory factory=HibernateUtil.getSessionFactory();
//管理二级缓存
//factory.evict(Student.class,1);
factory.evict(Student.class);
try{
//第二个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
//会发出查询sql 主要是由于二级缓存中的数据被清楚啦
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
/**
* 一级缓存和二级缓存的交互
* 默认为CacheMode.NORMAL
* 即以及缓存即向二级缓存中写数据也从二级缓存中读数据
*/
public void testCache(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
try{
//第2个session
session=HibernateUtil.getSession();
//仅从二级缓存读数据 而不从二级缓存写数据
session.setCacheMode(CacheMode.GET);
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
//不会发出sql 语句
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
SessionFactory factory=HibernateUtil.getSessionFactory();

try{
//第3个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
// 因为session设置了CacheMode位GET 所以二级缓存中没有数据
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
public void testCache2(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
try{
//第2个session
session=HibernateUtil.getSession();
//仅从二级缓写读数据 而不从二级缓读写数据
session.setCacheMode(CacheMode.PUT);
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
SessionFactory factory=HibernateUtil.getSessionFactory();

try{
//第3个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
// 因为session设置了CacheMode位GET 所以二级缓存中没有数据
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
}



---------------------------------------------------------------------
在运新单元测试之前请初始化数据 初始化数据类 请参照前一篇文章的的 InitialData类
运行了以上的单元测试 我们可以对hibernate的二级缓存 就会有个比较清晰的认识
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值