<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ? ? 最近在學習SHH框架中的Hibernate,對Session的get和load方法,有點混不清楚,不知道區別在哪,或者對它們的區別感觸不深。所以百度了一下,結果問題來了。百度的結果和實際測試的結果出入很大。主要是對get方法的說法跟實際運行的結果不一致。 ? ? 先說一下觀點吧: - get不支持lazy,load支持lazy; - 數據不存在時,get返回null,load則拋出ObjectNotFoundException異常。 - load方法可以返回實體的代理類實例,而get方法直接讀取數據庫,所以直接返回實體類(get的這個說法是錯誤的) ? ? 對于第一條,相信大家都沒有太多的疑問。我這里給個例子稍作解釋:lazy意味著用的時候才去執行sql語句。 ~~~ User user = (User)session.load(User.class,"4028981b41174a690141174a6c6d0003"); ~~~ 這句代碼不會去執行數據庫查詢,只有用到user時才會去執行數據庫查詢。所以不會立即生成sql語句。 ~~~ User user = (User)session.get(User.class, "4028981b41174a690141174a6c6d0003"); ~~~ 而上面這句代碼則會立即去執行數據庫查詢(如果緩存中沒有實例)。 ? ? 而后面的問題要想說明白,首先得了解一個問題——Session加載實體對象的過程: ? ? 首先,Hibernate中維持了兩級緩存。第一級緩存由Session實例維護,它是屬于事務范圍的緩存。其中保持了Session當前所有關聯實體的數據,也稱為內部緩存。而第二級緩存則存在于SessionFactory層次,它是屬于進程范圍或群集范圍的緩存,由當前所有由本SessionFactory構造的Session實例共享。 ? ? 出于性能考慮,避免無謂的數據庫訪問,Session在調用數據庫查詢功能**之前**,會先在緩存中進行查詢。首先在第一級緩存(內部緩存)中,通過實體類型和id進行查找,如果第一級緩存查找命中,且數據狀態合法,則直接返回。然后,Session會在當前“NonExists”記錄中進行查找,如果“NonExists”記錄中存在同樣的查詢條件,則返回null。 “NonExists” 記錄了當前Session實例在之前所有查詢操作中,未能查詢到有效數據的查詢條件(相當于一個查詢黑名單列表)。如此一來,如果Session中一個無效的查詢條件重復出現,即可迅速作出判斷,從而獲得最佳的性能表現。 ? ? 對于load方法而言,首先查找內部緩存,如果命中,則返回實例,如果內部緩存中未發現有效數據,則查詢第二級緩存,如果第二級緩存命中,則返回。若二級緩存中依舊未發現有效數據,則發起數據庫查詢操作(Select SQL)。如果查詢到,則返回實體類的**代理對象**,若經過查詢未發現對應記錄,則將此次查詢的信息在“NonExists” 中加以記錄,并拋出ObjectNotFoundException異常。 ? ? 對于get方法而言,**許多書上、網絡博客里都說錯了**。get方法同樣是先查找內部緩存,如果命中,則返回,否則發起數據庫查詢操作,如果查詢到,則返回實體類的對象,若經過查詢未發現對應記錄,則將此次查詢的信息在“NonExists” 中加以記錄,并返回null。所以網絡上說的“當他人修改了數據后,用load可能讀取不到最新的數據,而get肯定可以讀取到最新修改的數據”的說法也是**不成立**的。 ? ? 這也就意味著,get方法獲取到的并不一定是實體類對象,load方法也不一定是返回實體代理類對象。 ? ? 以上的觀點都是我通過測試得出來的,有代碼有圖有真相呀: ~~~ package com.bjpowernode.hibernate; import java.util.Date; import junit.framework.TestCase; import org.hibernate.ObjectNotFoundException; import org.hibernate.Session; import org.hibernate.Transaction; /** * Session測試類 * * @author Longxuan * */ public class SessionTest extends TestCase { public void testEquals() { Session session = null; try { //獲取Session session = HibernateUtils.getSession(); // 開啟事務 session.beginTransaction(); System.out.println("\n\n\n\n"); try { // 驗證查不到數據時,get返回null,load拋ObjectNotFoundException異常 System.out.println(session.get(User.class, "123")); System.out.println(session.load(User.class, "123")); } catch (ObjectNotFoundException e) { System.out.println("load方法拋出ObjectNotFoundException異常"); } System.out.println("\n\n"); // 驗證load返回實體類對象,而非代理對象 { User user1 = (User) session.get(User.class,"4028981b41174a690141174a6c6d0003"); User user2 = (User) session.load(User.class,"4028981b41174a690141174a6c6d0003"); System.out.println("user1:" + user1.getClass().getSimpleName()); System.out.println("user2:" + user2.getClass().getSimpleName()); System.out.println("user1與 user2是否為同一對象:" + user1.equals(user2)); } System.out.println("\n\n"); session.clear();//清除Session // 驗證get也可以返回代理類對象,而并不一定返回實體類對象 // 同時驗證了get方法先查找緩存(如果沒有輸出sql語句,則說明get查找了緩存) { User user3 = (User) session.load(User.class,"4028981b41174a690141174a6c6d0003"); User user4 = (User) session.get(User.class,"4028981b41174a690141174a6c6d0003"); System.out.println("user3:" + user3.getClass().getSimpleName()); System.out.println("user4:" + user4.getClass().getSimpleName()); System.out.println("user3與 user4是否為同一對象:" + user3.equals(user4)); } session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } } ~~~ 運行結果圖: ![](https://box.kancloud.cn/2016-02-18_56c53c0fc52b3.jpg) ? ? 還有一個有趣的現象: ~~~ User user5 = (User)session.load(User.class, "123"); System.out.println(user5.getId()); ~~~ ? ? 運行結果直接輸出 123 ? ? 從結果中也可以看出,前2句代碼,不會去執行數據庫操作。因為load后會在hibernate的一級緩存里存放一個map對象,該map的key就是Id的值,但是當你getId()時,它會去一級緩存里拿map的key值,正好找到了,所以不會再去執行數據庫查詢。也不會報任何錯。就有了以上的結果。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看