国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

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

2019-11-26 14:43:20
字體:
來源:轉載
供稿:網友

緩存

今天我們就來講一下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 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();  } 

  看到紅色的兩句代碼,這是我們進行添加的兩個開啟查詢緩存的代碼,現在我們看到結果:

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 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 简阳市| 江华| 大理市| 吉木萨尔县| 桐庐县| 根河市| 大石桥市| 南宫市| 福清市| 荥阳市| 昭觉县| 莱阳市| 伊金霍洛旗| 汾西县| 滨海县| 乐亭县| 岳普湖县| 乐东| 资兴市| 台南市| 闽清县| 红安县| 安泽县| 玉龙| 乾安县| 慈利县| 大渡口区| 镇坪县| 临潭县| 勃利县| 浮山县| 游戏| 甘孜县| 洪湖市| 齐齐哈尔市| 洛浦县| 遂昌县| 遂昌县| 大石桥市| 沁源县| 罗城|