19、hibernate二級緩存(hibernate筆記)

一、簡介

  • 二級緩存也稱進(jìn)程級的緩存或SessionFactory級的緩存,二級緩存可以被所有的session共享。二級緩存的生命周期和SessionFactory的一致,SessionFactory可以管理二級緩存。
  • 本身hibernate也提供二級緩存的工具,但是一般我們在實(shí)際開發(fā)中不使用,而是使用一些外部的二級緩存工具,這里介紹EhCache。

二、配置和使用

  • 1.首先當(dāng)然是加入相關(guān)的jar包,同時將配置文件ehcache.xml加入到src下。
  • 2.開啟二級緩存,修改hibernate.cfg.xml文件
  • 3.指定緩存產(chǎn)品提供商
  • 4.指定哪些實(shí)體使用二級緩存

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配置文件中都能查到 -->
        <property name="hibernate.connection.url">
            <![CDATA[jdbc:mysql://localhost:3305/hibernate_cache_level_2?useUnicode=true&characterEncoding=utf8]]>
        </property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">walp1314</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>
        
        <!-- 指定緩存產(chǎn)品提供商 -->
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        
        <mapping resource="cn/itcast/hibernate/Student.hbm.xml"/>
        <mapping resource="cn/itcast/hibernate/Classes.hbm.xml"/>
        <!-- 指定哪些實(shí)體使用二級緩存 -->
        <class-cache class="cn.itcast.hibernate.Student" usage="read-only"/>
    </session-factory>
</hibernate-configuration>

說明:

  • 這里我們在指定哪些實(shí)體類使用二級緩存的時候可以在上面的文件中進(jìn)行配置,這是推薦的方式,同時我們也可以在Student.hbm.xml中的class標(biāo)簽內(nèi)部使用<cache usage="read-only"/>進(jìn)行配置(不推薦)。

  • 因?yàn)橐话銓⒆兓淮蟮臄?shù)據(jù)放在二級緩存中,這樣才能發(fā)揮出緩存的功能,所以一般二級緩存的策略使用read-only。

  • 注意:read-only這種策略表示只讀,但是這樣就不能更改緩存,但是有時候我們修改了數(shù)據(jù)庫數(shù)據(jù)而緩存不能更改確實(shí)會造成錯誤,這里我們可以在ehcache.xml中對緩存的生命周期進(jìn)行配置,一定時間后讓緩存更新。

  • 注意:二級緩存也是緩存實(shí)體對象,對普通屬性不進(jìn)行緩存。

相關(guān)實(shí)體:
Student.java

private int id;
private String name;
private Classes classes;

Classes.java

private int id;
private String name;
private Set students;

配置:
Classes.hbm.xml

<?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 package="cn.itcast.hibernate">
    <class name="Classes" table="_classes">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <set name="students" inverse="true" cascade="all">
            <key column="classesid"/>
            <one-to-many class="Student"/>
        </set>
    </class>
</hibernate-mapping>

Student.hbm.xml

<?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="cn.itcast.hibernate.Student" table="_student">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <many-to-one name="classes" column="classesid"/>
    </class>
</hibernate-mapping>

ehcache.xml

<ehcache>
    <diskStore path="java.io.tmpdir"/>

    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

    <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        />

</ehcache>

測試:
CacheLevel2Test.java

package cn.itcast.hibernate;
import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import junit.framework.TestCase;
public class CacheLevel2Test extends TestCase {
    /**
     * 開啟兩個session,分別調(diào)用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();
            
            //不會發(fā)出sql,因?yàn)殚_啟了二級緩存,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,分別調(diào)用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();
            
            //不會發(fā)出sql,因?yàn)殚_啟了二級緩存,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,分別調(diào)用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();
            
            //會發(fā)出查詢sql,因?yàn)槎壘彺嬷械臄?shù)據(jù)被清除了
            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);
        }
    }
}

說明:從上面三個測試中可以發(fā)現(xiàn)load、get方法都是共享二級緩存的。注意第三個測試?yán)又械氖褂肧essionFactory清理緩存,可以指定只清除某一個對象。

一級緩存和二級緩存的交互:

  • 若將二級緩存的模式設(shè)置為GET方式則表示load等會去查詢緩存,但是不會向緩存中存數(shù)據(jù);
  • 若將二級緩存的模式設(shè)置為PUT方式則表示會向緩存中存數(shù)據(jù),但是不會到緩存中查數(shù)據(jù)。
/**
     * 一級緩存和二級緩存的交互
     */
    public void testCache4() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            
            //僅從二級緩存中讀數(shù)據(jù),而不向二級緩存中寫數(shù)據(jù)
            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();
            
            //發(fā)出sql語句,因?yàn)閟ession設(shè)置了CacheMode為GET,所以二級緩存中沒有數(shù)據(jù)
            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();
            
            //只向二級緩存寫數(shù)據(jù),而不從二級緩存讀數(shù)據(jù)
            session.setCacheMode(CacheMode.PUT);
            
            //會發(fā)出查詢sql,因?yàn)閟ession將CacheMode設(shè)置成了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);
        }
        
    }   
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容