程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 詳解Java的Hibernate框架中的緩存與二級緩存

詳解Java的Hibernate框架中的緩存與二級緩存

編輯:關於JAVA

詳解Java的Hibernate框架中的緩存與二級緩存。本站提示廣大學習愛好者:(詳解Java的Hibernate框架中的緩存與二級緩存)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解Java的Hibernate框架中的緩存與二級緩存正文


緩存

明天我們就來說一下hibernate中實體狀況和hibernate緩存。
 1)起首我們先來看一下實體狀況:
 實體狀況重要分三種:transient,persitent,detached。
 看英文應當就年夜概明確了吧。
 transient:是指數據還沒跟數據庫中的數據絕對應。
 persistent:是指數據跟數據庫中的數據絕對應,它的任何轉變都邑反應到數據庫中。
 detached:是指數據跟數據庫中的數據絕對應,但因為session被封閉,它所做的修正不會對數據庫的記載形成影響。
 上面我們直接代碼來:

Transaction tx = session.beginTransaction(); 
User user = new User(); 
user.setName("shun"); 
//這裡的user還未保留到數據庫,數據庫表中並沒有與之對應的記載,它為transient狀況 
session.save(user); 
tx.commit(); 
//提交以後user變成persistent狀況 
session.close(); 
//因為session封閉,此時的user為detached狀況,它的一切修正都不會反應到數據庫中。 
     
Session session2 = sessionFactory.openSession(); 
tx = session2.beginTransaction(); 
user.setName("shun123"); 
session2.saveOrUpdate(user); 
tx.commit(); 
//當我們挪用了saveOrUpdate以後,user從新變成persistent狀況,它的一切修正都邑反應到數據庫中。 
session2.close(); 

  我們看到代碼,起首我們界說了一個對象user,在未保留之前,它就是transient狀況,在數據庫中並沒有與它響應的記載。而當我們停止保留並提交修正後,user成為persistent狀況,在數據庫中有響應的一筆記錄。而當我們把session封閉後,user就釀成了detached狀況了,它的更改其實不會反應到數據庫中,除非我們手動挪用saveOrUpdate等響應的更新和添加辦法。而當我們直接想讓它從persistent到transient狀況,怎樣辦呢?直接刪除便可以了,刪除後對象就在數據庫中沒有對應的記載,也就成transient狀況了。
 
 hibernate的狀況轉換照樣比擬簡略的,當是transient狀況時,數據庫沒有記載對應,而persistent和detached時都有對應的記載,但獨一的差別是detached是在session封閉以後才有的狀況。那末transient和detached的差別又是甚麼呢?就是有無數據庫表記載對應的成績。
 
 2)看完了狀況我們來看一下hibernate的緩存
 hibernate的緩存分兩種,一級緩存和二級緩存。
 一級緩存:所謂的一級緩存也就是外部緩存。
 二級緩存:它包含運用級緩存,在hibernate就是所謂的SessionFactory緩存,別的一個是散布式緩存,這個是最平安的緩存方法。
 直接來看法式:

public static void main(String[] args) { 
 
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Session session = sessionFactory.openSession(); 
     
  User user = (User)session.load(User.class,new Long(29)); 
  System.out.println(user.getName()); 
     
  User user2 = (User)session.load(User.class,new Long(29)); 
  System.out.println(user2.getName()); 
     
  session.close(); 
} 

  看成果:

Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=? 
shun123123 
shun123123 

 例子中我們用了兩次load,但成果中只要一句SQL語句,這注解它只查詢了一次。
 為何呢?這也就是hibernate的緩存起感化了。第一次查詢終了後,hibernate後把查出來的實體放在緩存中,下一次查的時刻起首會查緩存,看有無對應ID的實體存在,假如有則直接掏出,不然則停止數據庫的查詢。
 
 上面我們把代碼修正成:

User user = (User)session.load(User.class,new Long(29)); 
System.out.println(user.getName()); 
     
session.evict(user);//把user從緩存中刪失落 
     
User user2 = (User)session.load(User.class,new Long(29)); 
System.out.println(user2.getName()); 
     
session.close(); 

  看到成果:

Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=? 
shun123123 
Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=? 
shun123123 

  本身我們把user從緩存中刪除後,第二次的查詢也直接從數據庫中掏出。

二級緩存小談
先看實體類:

public class User implements Serializable{ 
 
  public Long id; 
  private String name; 
  private int age; 
   
} 

  映照文件就省略啦,年夜家應當都邑寫的。
 再來看看hibernate設置裝備擺設文件:

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

   我們看到provider_class中我們指定了ehcache這個供給類,所以我們也須要ehcache.xml放在classpath中:

<?xml version="1.0" encoding="UTF-8"?> 
<ehcache> 
  <diskStore path="java.io.path"/> 
  <defaultCache  
    maxElementsInMemory="10000" 
    eternal="false" 
    timeToIdleSeconds="120" 
    timeToLiveSeconds="120" 
    overflowToDisk="true" 
    /> 
</ehcache> 

 接上去,我們直接看一下測試辦法:

public static void main(String[] args) { 
 
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Session session = sessionFactory.openSession(); 
 
  Query query = session.createQuery("from User user where name = 'shun123'"); 
  Iterator iter = query.iterate(); 
  while(iter.hasNext()) { 
    System.out.println(((User)iter.next()).getName()); 
  } 
   
  session.close(); 
   
  Session session2 = sessionFactory.openSession(); 
  Query query2 = session2.createQuery("from User user where name='shun123'"); 
  Iterator iter2 = query2.iterate(); 
  while(iter2.hasNext()) { 
    System.out.println(((User)iter2.next()).getName()); 
  } 
   
  session2.close(); 
 
} 

  運轉後可以看到:

Hibernate: select user0_.USER_ID as col_0_0_ from USER user0_ where user0_.USER_NAME='shun123' 
Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=? 
shun123 
Hibernate: select user0_.USER_ID as col_0_0_ from USER user0_ where user0_.USER_NAME='shun123' 
shun123 

  我們可以看到它只履行了一句搜刮,而在第二次查詢時並沒有掏出ID停止搜刮,這重要歸功於二級緩存。
 
 上面我們先剖析一下測試辦法中的代碼。測試辦法中我們分離翻開了兩個Session而且分離創立兩個Query停止雷同的查詢。但兩次Session可以共用緩存,這也就是二級緩存,SessionFactory級的緩存。只需我們的Session由統一個SessionFactory創立,那末我們便可以共用二級緩存削減與數據庫的交互。
 我們再來看一下設置裝備擺設文件中的意思:

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

  假如我們須要應用二級緩存,起首須要設置裝備擺設:

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

  停止開戶二級緩存,然後經由過程:

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

  指定二級緩存的供給類,普通情形下我們都用ehcache,其他我的臨時沒用到,也不太清晰,所以臨時不講了。
 像我們適才的例子,我們只須要設置裝備擺設下面兩個,完整可以正常運轉,應用二級緩存。
 那末第三句是干甚麼用的呢?

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

  這個設置裝備擺設指清楚明了我們在查詢時須要應用緩存,假如我們須要用到這個要事前挪用query.setCacheable(true)這個辦法來停止啟用。
 
 我們一路來看代碼(我們先不啟用緩存):

public static void main(String[] args) { 
 
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Session session = sessionFactory.openSession(); 
 
  Query query = session.createQuery("from User user where name = 'shun123'"); 
  List list = query.list(); 
  for (int i = 0; i < list.size(); i++){ 
    System.out.println(((User)list.get(i)).getName()); 
  } 
   
  session.close(); 
   
  Session session2 = sessionFactory.openSession(); 
  Query query2 = session2.createQuery("from User user where name='shun123'"); 
  List list2 = query2.list(); 
  for (int i = 0; i < list2.size(); i++){ 
    System.out.println(((User)list.get(i)).getName()); 
  } 
   
  session2.close(); 
 
} 

  這裡輸入的成果是:

Hibernate: select user0_.USER_ID as USER1_0_, user0_.USER_NAME as USER2_0_, user0_.age as age0_ from USER user0_ where user0_.USER_NAME='shun123' 
shun123 
Hibernate: select user0_.USER_ID as USER1_0_, user0_.USER_NAME as USER2_0_, user0_.age as age0_ from USER user0_ where user0_.USER_NAME='shun123' 
shun123 

  我們看到,它並沒有益用緩存,由於我們這裡用了list,而list對緩存是只寫不讀的。所以這裡會停止兩次查詢。
 那末我們來修正一下:

public static void main(String[] args) { 
 
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Session session = sessionFactory.openSession(); 
 
  Query query = session.createQuery("from User user where name = 'shun123'"); 
  <span ><span >query.setCacheable(true);</span></span> 
  List list = query.list(); 
  for (int i = 0; i < list.size(); i++){ 
    System.out.println(((User)list.get(i)).getName()); 
  } 
   
  session.close(); 
   
  Session session2 = sessionFactory.openSession(); 
  Query query2 = session2.createQuery("from User user where name='shun123'"); 
  <span >query2.setCacheable(true);</span> 
  List list2 = query2.list(); 
  for (int i = 0; i < list2.size(); i++){ 
    System.out.println(((User)list.get(i)).getName()); 
  } 
   
  session2.close(); 
 
} 

  看到白色的兩句代碼,這是我們停止添加的兩個開啟查詢緩存的代碼,如今我們看到成果:

Hibernate: select user0_.USER_ID as USER1_0_, user0_.USER_NAME as USER2_0_, user0_.age as age0_ from USER user0_ where user0_.USER_NAME='shun123' 
shun123 
shun123 

  只剩一次查詢了,為何呢?就在那兩句白色代碼處,我們開啟了緩存,記住,須要應用兩次。把兩個query都設成可緩存的能力應用查詢緩存。
 Criteria也是相似的做法,為免有些童鞋忘卻了Criteria怎樣寫了,我照樣放一下代碼:

public static void main(String[] args) { 
 
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Session session = sessionFactory.openSession(); 
 
  Criteria criteria1 = session.createCriteria(User.class); 
  criteria1.setCacheable(true); 
  criteria1.add(Restrictions.eq("name","shun123")); 
  List list = criteria1.list(); 
  for (int i = 0; i < list.size(); i++){ 
    System.out.println(((User)list.get(i)).getName()); 
  } 
   
  session.close(); 
   
  Session session2 = sessionFactory.openSession(); 
  Criteria criteria2 = session2.createCriteria(User.class); 
  criteria2.setCacheable(true); 
  criteria2.add(Restrictions.eq("name","shun123")); 
  List list2 = criteria2.list(); 
  for (int i = 0; i < list2.size(); i++){ 
    System.out.println(((User)list.get(i)).getName()); 
  } 
   
  session2.close(); 
 
} 

  我們看成果:

Hibernate: select this_.USER_ID as USER1_0_0_, this_.USER_NAME as USER2_0_0_, this_.age as age0_0_ from USER this_ where this_.USER_NAME=? 
shun123 
shun123 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved