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个类 :

Java代码 :
  1. public class Clazz {   
  2. private Integer id;   
  3. private String name;   
  4. private Set<Student> students=new HashSet<Student>();   
  5.  }   
  6. public class Student {   
  7. private Integer id;   
  8. private String name;   
  9. private Clazz clazz;   
   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类设置缓存):

Xml代码:
  1.     <class name="com.june.hibernate.Clazz" table="t_clazz">  
  2.    <id name="id">  
  3.        <generator class="native"></generator>  
  4.    </id>  
  5.    <property name="name"></property>       
  6.    <set name="students" inverse="true">  
  7.       <key column="clazz"/>  
  8.       <one-to-many class="com.june.hibernate.Student"/>  
  9.    </set>    
  10. </class>  
  11. <class name="com.june.hibernate.Student" table="t_student">  
  12.    <!--    
  13.    <cache usage="read-only"/>-->  
  14.    <id name="id">  
  15.        <generator class="native"></generator>  
  16.    </id>  
  17.    <property name="name"></property>       
  18.    <many-to-one name="clazz" cascade="save-update"></many-to-one>    
  19. </class>  
   	<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 配置文件:

Xml代码:
  1. <hibernate-configuration>  
  2.     <session-factory>  
  3.     <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
  4.     <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_cache_level_2</property>  
  5.     <property name="hibernate.connection.username">root</property>  
  6.     <property name="hibernate.connection.password">123456</property>  
  7.     <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>  
  8.     <property name="hibernate.show_sql">true</property>  
  9.     <!-- 开启二级缓存 hibernate默认就是开启的 -->  
  10.     <property name="hibernate.cache.use_second_level_cache">true</property>  
  11.     <!-- 指定缓存产品提供商 -->  
  12.     <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>  
  13.      <mapping resource="com/june/hibernate/Clazz.hbm.xml"/>  
  14.      <mapping resource="com/june/hibernate/Student.hbm.xml"/>  
  15.      <!-- 我推荐在此设置二级缓存 而不是在具体的类配置文件中设置 因为在此设置会对非常清楚的了解 那些是设了二级缓存的 那些是没有设的-->  
  16.      <class-cache class="com.june.hibernate.Student" usage="read-only"/>  
  17.     </session-factory>  
  18. </hibernate-configuration>  
<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>


测试用例:       

Java代码     
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);
     }
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值