Hibernate的clear(),flush(),evict()方法詳解

http://blog.csdn.net/wkcgy/article/details/6192839

Hibernate的clear(),flush(),evict()方法詳解

分類: Hibernate SSH 2011-02-18 11:02 944人閱讀 評論(1) 收藏 舉報

1.Clear 方法

      無論是Load 還是 Get 都會首先查找緩存(一級緩存) 如果沒有,纔會去數據庫查找,調用Clear() 方法,可以強制清除Session緩存。

例:

[c-sharp] view plaincopyprint?

public void testClear(){  

        Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  

        session.beginTransaction();  

        Teacher t = (Teacher) session.get(Teacher.class, 3);  

        System.out.println(t.getName());  

        Teacher t2 = (Teacher) session.get(Teacher.class, 3);  

        System.out.println(t2.getName());  

        session.getTransaction().commit();  

    }  

 

這裏雖然用了2 個 get 方法( get 方法會立即執行 sql 語句),但因爲第一次執行了會緩存一個 ID 爲 3 的實體,所以雖然有 2 個 get 方法只執行一次 SQL 語句。

 

 

public void testClear(){  

        Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  

        session.beginTransaction();  

        Teacher t = (Teacher) session.get(Teacher.class, 3);  

        System.out.println(t.getName());  

        session.clear();//這裏不clear只會執行一次sql語句,有clear會執行2次  

        Teacher t2 = (Teacher) session.get(Teacher.class, 3);  

        System.out.println(t2.getName());  

        session.getTransaction().commit();  

    }  

 

這裏在第2 次 get 前執行 session.clear(), 我們把 hibernate show_sql  出來,它就會執行 2 次 sql 語句了。 所以session.clear() 會清除緩存。

 

2.Flush方法

      可以強制進行從內存到數據庫的同步。

例:

 

    /** 

     * flush 強制與數據庫同步 

     */  

    public void testFlush(){  

        Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  

        session.beginTransaction();  

        Teacher t = (Teacher) session.get(Teacher.class, 3);  

        t.setName("yyy");  

 

        t.setName("yyyyy");  

        session.getTransaction().commit();  

    }  

 

看這段代碼,我們setName() 2 次, 但程序只會更改數據庫一次,在 commit 時。

 

 

    /** 

     * flush 強制與數據庫同步 

     */  

    public void testFlush(){  

        Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  

        session.beginTransaction();  

        Teacher t = (Teacher) session.get(Teacher.class, 3);  

        t.setName("yyy");  

        session.flush();//有flush會執行2次UPDAE,沒有會只執行一次  

        t.setName("yyyyy");  

        session.getTransaction().commit();  

    }  

 

我們在第2 次 setName ()時 執行 session.flush().

 

再看hibernate  執行的 sql  語句

[c-sharp] view plaincopyprint?

Hibernate:   

    update  

        Teacher   

    set  

        birthday=?,  

        name=?,  

        title=?   

    where  

        id=?  

Hibernate:   

    update  

        Teacher   

    set  

        birthday=?,  

        name=?,  

        title=?   

    where  

        id=?  

 

執行了2 次 Update

 

所以看出來flush 方法會強制與數據庫同步。

 

 

 

 

 

Flush方法是可以設置的,也就是 fulsh 什麼時候執行是可以設置的

 

 在session.beginTransaction 前設置 FlushMode

 

session.setFlushMode(FlushMode.Always|AUTO|COMMIT|NEVER|MANUAL)

 

FlushMode有 5 個值可選

Always:任何代碼都會 Flush 

AUTO:默認方式 – 自動 

Commit:COMMIT時 

Never:始終不 

MANUAL:手動方式

 

設置FlushMode  有個好處是可以節省開銷,比如默認 session 只做查詢時,就可以不讓他與數據庫同步了。

 

session.evict(obj) :會把指定的緩衝對象進行清除。 

 

  session.clear() :把緩衝區內的全部對象清除,但不包括操作中的對象。 

 

  Hibernate 執行的順序如下: 

 (1) 生成一個事務的對象,並標記當前的 Session 處於事務狀態(注:此時並未啓動數據庫級事務)。 

 (2) 應用使用 s.save 保存對象,這個時候 Session 將這個對象放入 entityEntries ,用來標記對象已經和當前的會話建立了關聯,由於應用對對象做了保存的操作, Session 還要在 insertions 中登記應用的這個插入行爲(行爲包括:對象引用、對象 id 、 Session 、持久化處理類)。 

 (3)s.evict 將對象從 s 會話中拆離,這時 s 會從 entityEntries 中將這個對象移出。 

 (4) 事務提交,需要將所有緩存 flush 入數據庫, Session 啓動一個事務,並按照 insert,update,……,delete 的順序提交所有之前登記的操作(注意:所有 insert 執行完畢後纔會執行 update ,這裏的特殊處理也可能會將你的程序搞得一團糟,如需要控制操作的執行順序,要善於使用 flush ),現在對象不在 entityEntries 中,但在執行 insert 的行爲時只需要訪問 insertions 就足夠了,所以此時不會有任何的異常。異常出現在插入後通知 Session 該對象已經插入完畢這個步驟上,這個步驟中需要將 entityEntries 中對象的 existsInDatabase 標誌置爲 true ,由於對象並不存在於 entityEntries 中,此時 Hibernate 就認爲 insertions 和 entityEntries 可能因爲線程安全的問題產生了不同步(也不知道 Hibernate 的開發者是否考慮到例子中的處理方式,如果沒有的話,這也許算是一個 bug 吧),於是一個 net.sf.hibernate.AssertionFailure 就被拋出,程序終止。 

 

         一般我們會錯誤的認爲 s.save 會立即執行,而將對象過早的與 Session 拆離,造成了 Session 的 insertions 和 entityEntries 中內容的不同步。所以我們在做此類操作時一定要清楚 Hibernate 什麼時候會將數據 flush 入數據庫,在未 flush 之前不要將已進行操作的對象從 Session 上拆離。解決辦法是在 save 之後,添加 session.flush 。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章