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

詳解Java的Hibernate框架中的緩存與二級(jí)緩存

 更新時(shí)間:2015年12月28日 17:26:42   作者:cxshun  
這篇文章主要介紹了Java的Hibernate框架中的緩存與二級(jí)緩存,Hibernate是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下

緩存

今天我們就來(lái)講一下hibernate中實(shí)體狀態(tài)和hibernate緩存。
 1)首先我們先來(lái)看一下實(shí)體狀態(tài):
 實(shí)體狀態(tài)主要分三種:transient,persitent,detached。
 看英文應(yīng)該就大概明白了吧。
 transient:是指數(shù)據(jù)還沒(méi)跟數(shù)據(jù)庫(kù)中的數(shù)據(jù)相對(duì)應(yīng)。
 persistent:是指數(shù)據(jù)跟數(shù)據(jù)庫(kù)中的數(shù)據(jù)相對(duì)應(yīng),它的任何改變都會(huì)反映到數(shù)據(jù)庫(kù)中。
 detached:是指數(shù)據(jù)跟數(shù)據(jù)庫(kù)中的數(shù)據(jù)相對(duì)應(yīng),但由于session被關(guān)閉,它所做的修改不會(huì)對(duì)數(shù)據(jù)庫(kù)的記錄造成影響。
 下面我們直接代碼來(lái):

Transaction tx = session.beginTransaction(); 
User user = new User(); 
user.setName("shun"); 
//這里的user還未保存到數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)表中并沒(méi)有與之對(duì)應(yīng)的記錄,它為transient狀態(tài) 
session.save(user); 
tx.commit(); 
//提交之后user變?yōu)閜ersistent狀態(tài) 
session.close(); 
//由于session關(guān)閉,此時(shí)的user為detached狀態(tài),它的所有修改都不會(huì)反映到數(shù)據(jù)庫(kù)中。 
     
Session session2 = sessionFactory.openSession(); 
tx = session2.beginTransaction(); 
user.setName("shun123"); 
session2.saveOrUpdate(user); 
tx.commit(); 
//當(dāng)我們調(diào)用了saveOrUpdate之后,user重新變?yōu)閜ersistent狀態(tài),它的所有修改都會(huì)反映到數(shù)據(jù)庫(kù)中。 
session2.close(); 

  我們看到代碼,首先我們定義了一個(gè)對(duì)象user,在未保存之前,它就是transient狀態(tài),在數(shù)據(jù)庫(kù)中并沒(méi)有與它相應(yīng)的記錄。而當(dāng)我們進(jìn)行保存并提交修改后,user成為persistent狀態(tài),在數(shù)據(jù)庫(kù)中有相應(yīng)的一條記錄。而當(dāng)我們把session關(guān)閉后,user就變成了detached狀態(tài)了,它的更改并不會(huì)反映到數(shù)據(jù)庫(kù)中,除非我們手動(dòng)調(diào)用saveOrUpdate等相應(yīng)的更新和添加方法。而當(dāng)我們直接想讓它從persistent到transient狀態(tài),怎么辦呢?直接刪除就可以了,刪除后對(duì)象就在數(shù)據(jù)庫(kù)中沒(méi)有對(duì)應(yīng)的記錄,也就成transient狀態(tài)了。
 
 hibernate的狀態(tài)轉(zhuǎn)換還是比較簡(jiǎn)單的,當(dāng)是transient狀態(tài)時(shí),數(shù)據(jù)庫(kù)沒(méi)有記錄對(duì)應(yīng),而persistent和detached時(shí)都有對(duì)應(yīng)的記錄,但唯一的區(qū)別是detached是在session關(guān)閉之后才有的狀態(tài)。那么transient和detached的區(qū)別又是什么呢?就是有沒(méi)有數(shù)據(jù)庫(kù)表記錄對(duì)應(yīng)的問(wèn)題。
 
 2)看完了狀態(tài)我們來(lái)看一下hibernate的緩存
 hibernate的緩存分兩種,一級(jí)緩存和二級(jí)緩存。
 一級(jí)緩存:所謂的一級(jí)緩存也就是內(nèi)部緩存。
 二級(jí)緩存:它包括應(yīng)用級(jí)緩存,在hibernate就是所謂的SessionFactory緩存,另外一個(gè)是分布式緩存,這個(gè)是最安全的緩存方式。
 直接來(lái)看程序:

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(); 
} 

  看結(jié)果:

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,但結(jié)果中只有一句SQL語(yǔ)句,這表明它只查詢(xún)了一次。
 為什么呢?這也就是hibernate的緩存起作用了。第一次查詢(xún)完畢后,hibernate后把查出來(lái)的實(shí)體放在緩存中,下一次查的時(shí)候首先會(huì)查緩存,看有沒(méi)有對(duì)應(yīng)ID的實(shí)體存在,如果有則直接取出,否則則進(jìn)行數(shù)據(jù)庫(kù)的查詢(xún)。
 
 下面我們把代碼修改成:

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(); 

  看到結(jié)果:

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從緩存中刪除后,第二次的查詢(xún)也直接從數(shù)據(jù)庫(kù)中取出。

二級(jí)緩存小談
先看實(shí)體類(lèi):

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

  映射文件就省略啦,大家應(yīng)該都會(huì)寫(xiě)的。
 再來(lái)看看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這個(gè)提供類(lèi),所以我們也需要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> 

 接下來(lái),我們直接看一下測(cè)試方法:

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(); 
 
} 

  運(yùn)行后可以看到:

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 

  我們可以看到它只執(zhí)行了一句搜索,而在第二次查詢(xún)時(shí)并沒(méi)有取出ID進(jìn)行搜索,這主要?dú)w功于二級(jí)緩存。
 
 下面我們先分析一下測(cè)試方法中的代碼。測(cè)試方法中我們分別打開(kāi)了兩個(gè)Session并且分別創(chuàng)建兩個(gè)Query進(jìn)行相同的查詢(xún)。但兩次Session可以共用緩存,這也就是二級(jí)緩存,SessionFactory級(jí)的緩存。只要我們的Session由同一個(gè)SessionFactory創(chuàng)建,那么我們就可以共用二級(jí)緩存減少與數(shù)據(jù)庫(kù)的交互。
 我們?cè)賮?lái)看一下配置文件中的意思:

<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> 

  如果我們需要使用二級(jí)緩存,首先需要配置:

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

  進(jìn)行開(kāi)戶(hù)二級(jí)緩存,然后通過(guò):

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

  指定二級(jí)緩存的提供類(lèi),一般情況下我們都用ehcache,其他我的暫時(shí)沒(méi)用到,也不太清楚,所以暫時(shí)不講了。
 像我們剛才的例子,我們只需要配置上面兩個(gè),完全可以正常運(yùn)行,利用二級(jí)緩存。
 那么第三句是干什么用的呢?

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

  這個(gè)配置指明了我們?cè)诓樵?xún)時(shí)需要利用緩存,如果我們需要用到這個(gè)要事先調(diào)用query.setCacheable(true)這個(gè)方法來(lái)進(jìn)行啟用。
 
 我們一起來(lái)看代碼(我們先不啟用緩存):

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(); 
 
} 

  這里輸出的結(jié)果是:

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 

  我們看到,它并沒(méi)有利用緩存,因?yàn)槲覀冞@里用了list,而list對(duì)緩存是只寫(xiě)不讀的。所以這里會(huì)進(jìn)行兩次查詢(xún)。
 那么我們來(lái)修改一下:

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 style="background-color: #ffffff;"><span style="color: #ff0000;">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 style="color: #ff0000;">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(); 
 
} 

  看到紅色的兩句代碼,這是我們進(jìn)行添加的兩個(gè)開(kāi)啟查詢(xún)緩存的代碼,現(xiàn)在我們看到結(jié)果:

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 

  只剩一次查詢(xún)了,為什么呢?就在那兩句紅色代碼處,我們開(kāi)啟了緩存,記住,需要使用兩次。把兩個(gè)query都設(shè)成可緩存的才能使用查詢(xún)緩存。
 Criteria也是類(lèi)似的做法,為免有些童鞋忘記了Criteria怎么寫(xiě)了,我還是放一下代碼:

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(); 
 
} 

  我們看結(jié)果:

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 

相關(guān)文章

  • Java并發(fā)編程之volatile與JMM多線程內(nèi)存模型

    Java并發(fā)編程之volatile與JMM多線程內(nèi)存模型

    這篇文章主要介紹了Java并發(fā)volatile與JMM多線程內(nèi)存模型,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • Java的內(nèi)部類(lèi)總結(jié)

    Java的內(nèi)部類(lèi)總結(jié)

    這篇文章主要為大家介紹了Java的內(nèi)部類(lèi),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • Java多線程中斷機(jī)制三種方法及示例

    Java多線程中斷機(jī)制三種方法及示例

    這篇文章主要介紹了Java多線程中斷機(jī)制三種方法及示例,向大家分享了這三種方法的介紹幾代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • HttpUtils 發(fā)送http請(qǐng)求工具類(lèi)(實(shí)例講解)

    HttpUtils 發(fā)送http請(qǐng)求工具類(lèi)(實(shí)例講解)

    下面小編就為大家?guī)?lái)一篇HttpUtils 發(fā)送http請(qǐng)求工具類(lèi)(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • 基于FLink實(shí)現(xiàn)實(shí)時(shí)安全檢測(cè)的示例代碼

    基于FLink實(shí)現(xiàn)實(shí)時(shí)安全檢測(cè)的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何基于FLink實(shí)現(xiàn)實(shí)時(shí)安全檢測(cè)的功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的可以了解一下
    2023-02-02
  • 一文帶你了解如何正確使用Java中的字符串常量池

    一文帶你了解如何正確使用Java中的字符串常量池

    研究表明,Java堆中對(duì)象占據(jù)最大比重的就是字符串對(duì)象,所以弄清楚字符串知識(shí)對(duì)學(xué)習(xí)Java很重要。本文主要重點(diǎn)聊聊字符串常量池,希望對(duì)大家有所幫助
    2022-12-12
  • Java 位圖法排序的使用方法

    Java 位圖法排序的使用方法

    本篇文章,小編將為大家介紹關(guān)于Java 位圖法排序的使用方法,有需要的朋友可以參考一下
    2013-04-04
  • SpringBoot整合freemarker實(shí)現(xiàn)代碼生成器

    SpringBoot整合freemarker實(shí)現(xiàn)代碼生成器

    這篇文章主要為大家詳細(xì)介紹了SpringBoot如何整合freemarker實(shí)現(xiàn)一個(gè)簡(jiǎn)單的代碼生成器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-03-03
  • Java中方法的使用、重載與遞歸的詳細(xì)介紹

    Java中方法的使用、重載與遞歸的詳細(xì)介紹

    前面我們提到了方法需要參數(shù)類(lèi)型,但是如果我們需要用一個(gè)函數(shù)同時(shí)兼容多種參數(shù)的情況應(yīng)該怎么辦呢? 這里就可以使用到方法重載,對(duì)Java中方法的使用、重載與遞歸相關(guān)知識(shí)感興趣的朋友一起看看吧
    2021-11-11
  • 聊聊Spring Cloud Cli 初體驗(yàn)

    聊聊Spring Cloud Cli 初體驗(yàn)

    這篇文章主要介紹了聊聊Spring Cloud Cli 初體驗(yàn),SpringBoot CLI 是spring Boot項(xiàng)目的腳手架工具。非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-04-04

最新評(píng)論