欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Hibernate緩存機制實例代碼解析

 更新時間:2018年02月08日 08:37:08   作者:lavimer  
這篇文章主要介紹了Hibernate緩存機制實例代碼解析,介紹了查詢緩存,一級二級緩存等內容,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下

本文研究的主要是Hibernate緩存機制的相關內容,具體如下。

演示項目:

Student.java:

public class Student {
	/*學生ID*/
	private int id;
	/*學生姓名*/
	private String name;
	/*學生和班級的關系*/
	private Classes classes;
	//省略setter和getter方法
}

Classes.java:

public class Classes {
	/*班級ID*/
	private int id;
	/*班級名稱*/
	private String name;
	/*班級和學生的關系*/
	private Set<Student> students;
	//省略setter和getter方法
}

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 package="com.lixue.bean"> 
  <class name="Student" table="t_student"> 
    <id name="id"> 
      <generator class="native"/> 
    </id> 
    <!-- 映射普通屬性 --> 
    <property name="name"/> 
    <!-- 多對一 映射,在多的一端加上外鍵--> 
    <many-to-one name="classes" column="classesid"/> 
  </class> 
</hibernate-mapping> 

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="com.lixue.bean"> 
  <!-- 設置lazy為false --> 
  <class name="Classes" table="t_classes" lazy="false"> 
    <id name="id"> 
      <generator class="native"/> 
    </id> 
    <property name="name"/> 
    <!-- 一對多映射 ,inverse="true"表示交給對端維護關系--> 
    <set name="students" inverse="true"> 
       <key column="classesid"/> 
      <one-to-many class="Student"/> 
    </set> 
  </class> 
</hibernate-mapping> 

一級緩存:

一級緩存聲明周期很短和session的生命周期一致,一級緩存也叫session級的緩存或事物級緩存,一級緩存是緩存對象的,并不能緩存屬性。

測試方法(在同一個session中使用load()查詢兩次):

/*取出來之后會放在緩存中,第二次取的時候會直接從緩存取出*/ 
      Student student = (Student)session.load(Student.class, 1); 
      System.out.println("student.name=" + student.getName()); 
       
      /*不會發(fā)出查詢語句,load使用緩存*/ 
      student = (Student)session.load(Student.class, 1); 
      System.out.println("student.name=" + student.getName()); 

注:我們會發(fā)現(xiàn),當我們第一次查詢的時候,查出來的結果是會放在session即緩存即一級緩存中的。第二次load()后及時去獲取值的時候也沒有在發(fā)出語句到數(shù)據(jù)庫中查詢了,而是直接從緩存中取值了(必須是在同一session中)。

測試方法二(在同一session中):

Student student = new Student(); 
      student.setName("張三"); 
      Serializable id = session.save(student); 
      student = (Student)session.load(Student.class, id); 
      //不會發(fā)出查詢語句,因為save支持緩存 
      System.out.println("student.name=" + student.getName()); 

注:調用了save()方法再使用load()去加載對象,然后真正獲取name屬性,但是此時并不會發(fā)出語句去查詢數(shù)據(jù)庫。因為save()方法也是支持緩存的。

測試大批量數(shù)據(jù)的添加:

public void testCache7() { 
    Session session = null; 
    try { 
      session = HibernateUtils.getSession(); 
      session.beginTransaction(); 
      for (int i=0; i<100; i++) { 
        Student student = new Student(); 
        student.setName("張三" + i); 
        session.save(student); 
        //每20條更新一次 
        if (i % 20 == 0) { 
          //清除緩存,調用flush之后數(shù)據(jù)就會保存到數(shù)據(jù)庫 
          session.flush(); 
          //清除緩存的內容 
          session.clear(); 
        } 
      } 
      session.getTransaction().commit(); 
    }catch(Exception e) { 
      e.printStackTrace(); 
      session.getTransaction().rollback(); 
    }finally { 
      HibernateUtils.closeSession(session); 
    } 
  } 

注:

1.因為save()方法支持緩存,那就存在一個問題,如果我要同時存1000萬條數(shù)據(jù),那緩存中豈不是有1000萬的緩存對象,那就很可能導致溢出。所以說Hibernate并不能很好的支持大批量數(shù)據(jù)的更新操作,但是我們也可以很靈活的處理這個問題,比如使用循環(huán)每20條數(shù)據(jù)清除一次緩存。

2.save,update,saveOrUpdate,load,get,list,iterate,lock這些方法都會將對象放在一級緩存中,一級緩存不能控制緩存的數(shù)量,所以要注意大批量操作數(shù)據(jù)時可能造成內存溢出;可以用evict,clear方法清除緩存中的內容。

二級緩存:

二級緩存也稱為進程級緩存或SessionFactory級緩存,二級緩存可以被所有的session緩存共享。二級緩存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二級緩存,二級緩存的原則是當讀遠大于寫的時候使用,二級緩存也主要是緩存實體對象的。

二級緩存的配置:

1.將ehcahe.xml文件拷貝到src目錄下。

2.在Hibernate.cfg.xml文件中加入緩存產(chǎn)品提供商,如下:

<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> 

3.啟用二級緩存(可以不顯示啟動,因為默認就是啟用的),如下:

<property name="hibernate.cache.use_second_level_cache">true</property>

4.指定哪些實體類使用二級緩存。

5.導入緩存使用的接口jar包:lib\optional\ehcache\ehcache-core-2.4.3.jar

ehcache.xml文件的內容:

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

注:

1.maxElementsInMemory表示緩存中最多存放的對象。

2.eternal表示是否永遠不過期(設置為false更有實際意義,如果為true的話表示永遠不過期,那么下面的屬性都沒什么意義了)。

3.timeToIdleSecods表示一個對象第一次被訪問后經(jīng)過多長時間沒被訪問就清除。

4.timeToLiveSecods表示一個對象的存貨時間。

5.overflowToDisk為true表示緩存中超出了maxElementsInMemory指定的個數(shù)就存到磁盤中。

指定溢出時保存的磁盤路徑:

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

注:這個路徑可以改。

測試方法(一級緩存的前提是必須在同一個session,現(xiàn)在我們使用二級緩存來看看在兩個不同的session中是否存在緩存):

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();
		Student student = (Student)session.load(Student.class, 1);
		//不會發(fā)出查詢語句,因為配置二級緩存,session可以共享二級緩存中的數(shù)據(jù) 
		//二級緩存是進程級的緩存 
		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),即使第一個session關閉了,再開啟另外一個session去加載數(shù)據(jù)也不會發(fā)出語句到數(shù)據(jù)庫中去查詢數(shù)據(jù),因為配置了二級緩存,它是整個sessionFactory共享的。

禁用二級緩存實現(xiàn)大批量數(shù)據(jù)的添加:

public void testCache5() { 
    Session session = null; 
    try { 
      session = HibernateUtils.getSession(); 
      session.beginTransaction(); 
       
      //禁止一級緩存和二級緩存交互 
      session.setCacheMode(CacheMode.IGNORE); 
      for (int i=0; i<100; i++) { 
        Student student = new Student(); 
        student.setName("張三" + i); 
        session.save(student); 
        //每20條更新一次 
        if (i % 20 == 0) { 
          session.flush(); 
          //清除緩存的內容 
          session.clear(); 
        } 
      } 
      session.getTransaction().commit(); 
    }catch(Exception e) { 
      e.printStackTrace(); 
      session.getTransaction().rollback(); 
    }finally { 
      HibernateUtils.closeSession(session); 
    } 
  }  

注:session.flush()表示清除一級緩存,但是我們又開起了二級緩存,save()之后也保存到了二級緩存,還是存在緩存過大導致溢出的情況。所以這種情況下我們應該禁用二級緩存:session.setCacheMode(CacheMode.IGNORE);

查詢緩存:一級緩存和二級緩存都是緩存實體對象的,但是有些時候我們希望獲取某些屬性的時候也不要頻繁的去訪問數(shù)據(jù)庫,而是從緩存中獲取,此時我們就可以使用查詢緩存。另外查詢緩存對實體對象的結果集會緩存ID。查詢緩存的生命周期,當關聯(lián)的表發(fā)生修改,查詢緩存的聲明周期就結束,和session的生命周期無關。

配置查詢緩存:

1.修改hibernate.cfg.xml文件,來開啟查詢緩存,默認是false即不開啟的,應如下設置:

<property name="hibernate.cache.use_query_cache">true</property> 

2.必須在程序中啟用,如:

query.setCacheable(true) 

測試方法:

public void testCache2() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		List names = session.createQuery("select s.name from Student s") 
		                .setCacheable(true) 
		                .list();
		for (int i=0; i<names.size(); i++) {
			String name = (String)names.get(i);
			System.out.println(name);
		}
		session.getTransaction().commit();
	}
	catch(Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	}
	finally {
		HibernateUtils.closeSession(session);
	}
	System.out.println("-------------------------------------------------------");
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		//不會發(fā)出查詢語句,因為查詢緩存和session的生命周期沒有關系 
		List names = session.createQuery("select s.name from Student s") 
		                .setCacheable(true) 
		                .list();
		for (int i=0; i<names.size(); i++) {
			String name = (String)names.get(i);
			System.out.println(name);
		}
		session.getTransaction().commit();
	}
	catch(Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	}
	finally {
		HibernateUtils.closeSession(session);
	}
}

注:上述代碼中,我們關閉了二級緩存,開啟了查詢緩存,然后查詢普通屬性。運行測試代碼我們可以發(fā)現(xiàn),在第一個session中第一次查詢發(fā)出了一條語句,然后關閉了session,接著再第二個session中進行查詢,我們會發(fā)現(xiàn)第二個session中的查詢并沒有發(fā)出語句,這說明查詢緩存和session的生命周期沒有什么關系。

hibernate.cfg.xml的緩存配置:

<!-- 設置指定二級緩存的實現(xiàn)接口 --> 
    <property name="hibernate.cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property> 
    <!-- 設置二級緩存所使用的配置文件 --> 
    <property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property> 
    <!-- 設置使用QUERY查詢緩存 --> 
    <property name="hibernate.cache.use_query_cache">true</property> 
     
    <!-- 加載對象關系映射文件 --> 
    <mapping resource="com/lixue/bean/Classes.hbm.xml" /> 
    <mapping resource="com/lixue/bean/Student.hbm.xml" /> 
     
    <!-- 必須先引入資源映射文件(就是實體映射文件)后再設置有使用二級緩存的實體類 --> 
    <class-cache usage="read-only" class="com.lixue.bean.Student" /> 

總結

以上就是本文關于Hibernate緩存機制實例代碼解析的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關文章

  • spring中@Transactional?注解失效的原因及解決辦法

    spring中@Transactional?注解失效的原因及解決辦法

    面試中經(jīng)常會被問到事務失效的場景有哪些,本文主要介紹了spring中@Transactional?注解失效的原因及解決辦法,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • 在SpringMVC框架下實現(xiàn)文件的上傳和下載示例

    在SpringMVC框架下實現(xiàn)文件的上傳和下載示例

    本篇文章主要介紹了在SpringMVC框架下實現(xiàn)文件的上傳和下載示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • Java對int[]數(shù)組做新增刪除去重操作代碼

    Java對int[]數(shù)組做新增刪除去重操作代碼

    這篇文章主要介紹了Java里面對int[]數(shù)組做新增刪除去重實現(xiàn),這里記錄下使用int[]數(shù)組對數(shù)組進行新增刪除去重等操作,用來更加了解java里面的集合類思想,需要的朋友可以參考下
    2023-10-10
  • 詳解SpringMVC的攔截器參數(shù)及攔截器鏈配置

    詳解SpringMVC的攔截器參數(shù)及攔截器鏈配置

    攔截器(Interceptor)是一種動態(tài)攔截方法調用的機制,在SpringMVC中動態(tài)攔截控制器方法的執(zhí)行。本文將詳細講講SpringMVC中攔截器參數(shù)及攔截器鏈配置,感興趣的可以嘗試一下
    2022-07-07
  • Javaweb實現(xiàn)在線人數(shù)統(tǒng)計代碼實例

    Javaweb實現(xiàn)在線人數(shù)統(tǒng)計代碼實例

    這篇文章主要介紹了Javaweb實現(xiàn)在線人數(shù)統(tǒng)計代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Java文件IO操作教程之DirectIO的意義

    Java文件IO操作教程之DirectIO的意義

    這篇文章主要給大家介紹了關于Java文件IO操作教程之DirectIO的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-03-03
  • Springboot整合WebSocket實戰(zhàn)教程

    Springboot整合WebSocket實戰(zhàn)教程

    WebSocket使得客戶端和服務器之間的數(shù)據(jù)交換變得更加簡單,允許服務端主動向客戶端推送數(shù)據(jù),這篇文章主要介紹了Springboot整合WebSocket實戰(zhàn)教程,需要的朋友可以參考下
    2023-05-05
  • 詳解Java中的防抖和節(jié)流

    詳解Java中的防抖和節(jié)流

    防抖是將多次執(zhí)行變?yōu)橹付〞r間內不在觸發(fā)之后,執(zhí)行一次。節(jié)流是將多次執(zhí)行變?yōu)橹付〞r間不論觸發(fā)多少次,時間一到就執(zhí)行一次。這篇文章來和大家聊聊Java中的防抖和節(jié)流,感興趣的可以了解一下
    2022-08-08
  • Java類型轉換valueOf與parseInt區(qū)別探討解析

    Java類型轉換valueOf與parseInt區(qū)別探討解析

    這篇文章主要為大家介紹了Java類型轉換valueOf與parseInt區(qū)別探討解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • JAVA多線程編程實例詳解

    JAVA多線程編程實例詳解

    這篇文章主要介紹了JAVA多線程編程,結合實例形式總結分析了多線程、鎖、線程池等相關原理及使用技巧,需要的朋友可以參考下
    2019-09-09

最新評論