天天看點

Hibernate_Session 緩存(Hibernate 一級緩存)

在 Session 接口的實作中包含一系列的 Java 集合, 這些 Java 集合構成了 Session 緩存. 隻要 Session 執行個體沒有結束生命周期, 且沒有清理緩存,則存放在它緩存中的對象也不會結束生命周期

Session 緩存可減少 Hibernate 應用程式通路資料庫的頻率。

News news = (News) session.get(News.class, 1);
System.out.println(news);
News news2 = (News) session.get(News.class, 1);
System.out.println(news2);
                

以上語句隻會發送一條sql語句

flush:Session 按照緩存中對象的屬性變化來同步更新資料庫

預設情況下 Session 在以下時間點重新整理緩存:

顯式調用 Session 的 flush() 方法

當應用程式調用 Transaction 的 commit()方法的時, 該方法先 flush ,然後在向資料庫送出事務

當應用程式執行一些查詢(HQL, Criteria)操作時,如果緩存中持久化對象的屬性已經發生了變化,會先 flush 緩存,以保證查詢結果能夠反映持久化對象的最新狀态

flush 緩存的例外情況: 如果對象使用 native 生成器生成 OID, 那麼當調用 Session 的 save() 方法儲存對象時, 會立即執行向資料庫插入該實體的 insert 語句.

commit() 和 flush() 方法的差別:flush 執行一系列 sql 語句,但不送出事務;commit 方法先調用flush() 方法,然後送出事務. 意味着送出事務意味着對資料庫操作永久儲存下來。

/**
     * flush: 使資料表中的記錄和 Session 緩存中的對象的狀态保持一緻. 為了保持一緻, 則可能會發送對應的 SQL 語句.
     * 1. 在 Transaction 的 commit() 方法中: 先調用 session 的 flush 方法, 再送出事務
     * 2. flush() 方法會可能會發送 SQL 語句, 但不會送出事務. 
     * 3. 注意: 在未送出事務或顯式的調用 session.flush() 方法之前, 也有可能會進行 flush() 操作.
     * 1). 執行 HQL 或 QBC 查詢, 會先進行 flush() 操作, 以得到資料表的最新的記錄
     * 2). 若記錄的 ID 是由底層資料庫使用自增的方式生成的, 則在調用 save() 方法時, 就會立即發送 INSERT 語句. 
     * 因為 save 方法後, 必須保證對象的 ID 是存在的!
     */
    @Test
    public void testSessionFlush2(){
        News news = new News("Java", "SUN", new Date());
        session.save(news);
    }
    
    @Test
    public void testSessionFlush(){
        News news = (News) session.get(News.class, 1);
        news.setAuthor("Oracle");
        
//        session.flush();
//        System.out.println("flush");
        //執行 HQL 或 QBC 查詢, 會先進行 flush() 操作, 以得到資料表的最新的記錄
        News news2 = (News) session.createCriteria(News.class).uniqueResult();
        System.out.println(news2);
    }
                
/**
     * refresh(): 會強制發送 SELECT 語句, 以使 Session 緩存中對象的狀态和資料表中對應的記錄保持一緻!
     */
    @Test
    public void testRefresh(){
        News news = (News) session.get(News.class, 1);
        System.out.println(news);
        
        session.refresh(news); 
        System.out.println(news); 
    }
                

以上的

refresh()

要把資料庫的隔離級别設定為以下才有用:

<!-- 設定 Hibernate 的事務隔離級别 -->
<property name="connection.isolation">2</property>
           
/**
     * clear(): 清理緩存
     */
    @Test
    public void testClear(){
        News news1 = (News) session.get(News.class, 1);
        
        session.clear();
        
        News news2 = (News) session.get(News.class, 1);
    }
                

以上代碼會發送兩條sql語句,因為clear()已經把緩存清理掉了

繼續閱讀