日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate数据保存操作方法的原理对比

發布時間:2024/4/17 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate数据保存操作方法的原理对比 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://fantasyyong.iteye.com/blog/146685

首先看看中文翻譯的Hibernate的Session的javadoc

Interface Session
All Superinterfaces:
Serializable
All Known Subinterfaces:
EventSource, Session
All Known Implementing Classes:
SessionImpl

public interface Session? extends Serializable

Java應用程序與Hibernate之間的主要運行時接口。它是抽象了持久化服務概念的核心抽象API類。

Session的生命周期綁定在一個物理的事務(tansaction)上面。(長的事務可能跨越多個數據庫事物。)

引用
Session的主要功能是提供對映射的實體類實例的創建,讀取和刪除操作。
實例可能以下面三種狀態存在:
瞬態或者自由態(transient): 不曾進行持久化,未與任何Session相關聯
持久化狀態(persistent): 僅與一個Session相關聯
脫管狀態或者游離態(detached): 已經進行過持久化,但當前未與任何Session相關聯

游離狀態的實例可以通過調用save()、persist()或者saveOrUpdate()方法進行持久化。
持久化實例可以通過調用 delete()變成游離狀態。
通過get()或load()方法得到的實例都是持久化狀態的。
游離狀態的實例可以通過調用 update()、0saveOrUpdate()、lock()或者replicate()進行持久化。
游離或者自由狀態下的實例可以通過調用merge()方法成為一個新的持久化實例。

save()和persist()將會引發SQL的INSERT,delete()會引發SQLDELETE,而update()或merge()會引發SQLUPDATE。
對持久化(persistent)實例的修改在刷新提交的時候會被檢測到,它也會引起SQLUPDATE。
saveOrUpdate()或者replicate()會引發SQLINSERT或者UPDATE。



其具體實現并不一定是線程安全的。每個線程/事務應該從一個SessionFactory獲取自己的session實例。

如果其持久化對象類是可序列化的,則Session實例也是可序列化的。

一個典型的事務應該使用下面的形式:

Java代碼 ?
  • Session?sess?=?factory.openSession(); ??
  • Transaction?tx; ??
  • try?{ ??
  • ????tx?=?sess.beginTransaction(); ??
  • ????//do?some?work ??
  • ????... ??
  • ????tx.commit(); ??
  • } ??
  • catch?(Exception?e)?{ ??
  • ????if?(tx!=null)?tx.rollback(); ??
  • ????throw?e; ??
  • } ??
  • finally?{ ??
  • ????sess.close(); ??
  • }??
  • Session sess = factory.openSession();Transaction tx;try {tx = sess.beginTransaction();//do some work...tx.commit();}catch (Exception e) {if (tx!=null) tx.rollback();throw e;}finally {sess.close();}




    如果Session拋出了異常, 事務必須回滾而session會被廢棄。在異常發生后Session的內部狀態可能會與數據庫失去同步。

    引用
    save方法
    public Serializable save(Object object)
    ????????????????? throws HibernateException

    Persist the given transient instance, first assigning a generated identifier.
    (Or using the current value of the identifier property if the assigned generator is used.)
    This operation cascades to associated instances if the association is mapped with cascade="save-update".
    持久化指定的游離態對象,首先要分配一個自動生成的主鍵標示符。
    (或者如果主鍵生成器正在使用,使用當前主鍵標示符屬性值)
    如果關聯關系映射配置了cascade="save-update"屬性,save操作對關聯對象級聯操作。
    Parameters:
    object - a transient instance of a persistent class
    一個要持久化類的自由狀態的實例對象
    Returns:
    the generated identifier
    返回生成的主鍵標示符
    Throws:
    HibernateException



    實例:
    Session.save()方法用于實體對象的持久化保存,也就是說當執行session.save()方法時會生成對應的insert SQL語句,完成數據的保存。
    如下面的代碼:

    Java代碼 ?
  • public?static?void?insertUser() ??
  • { ??
  • ????Session?sess?=?HibernateSessionFactory.getSession(); ??
  • ????User?user?=?new?User(); ??
  • ????Transaction?tx?=?null; ??
  • ????try??
  • ????{ ??
  • ????????tx?=?sess.beginTransaction(); ??
  • ????????//?do?some?work ??
  • ????????user.setLogonName("關羽"); ??
  • ????????user.setNickName("關云長"); ??
  • ????????user.setPassword("1234"); ??
  • ????????sess.save(user); ??
  • ????????tx.commit(); ??
  • ????} ??
  • ????catch?(Exception?e) ??
  • ????{ ??
  • ????????if?(tx?!=?null) ??
  • ????????????tx.rollback(); ??
  • ????} ??
  • ????finally??
  • ????{ ??
  • ????????sess.close(); ??
  • ????} ??
  • }??
  • public static void insertUser(){Session sess = HibernateSessionFactory.getSession();User user = new User();Transaction tx = null;try{tx = sess.beginTransaction();// do some workuser.setLogonName("關羽");user.setNickName("關云長");user.setPassword("1234");sess.save(user);tx.commit();}catch (Exception e){if (tx != null)tx.rollback();}finally{sess.close();}}



    當執行到session.save()方法時,Hibernate并不會馬上生成insert SQL語句來進行數據的保存,而是當稍后清理session的緩存時才有可能執行insert SQL語句,那么session.save()方法到底會執行哪些步驟呢?

    Hibernate3.2中save()方法實現的源代碼:

    引用
    Java代碼 ?
  • /** ?
  • ?*?Concrete?implementation?of?a?Session,?and?also?the?central,?organizing?component ?
  • ?*?of?Hibernate's?internal?implementation.?As?such,?this?class?exposes?two?interfaces; ?
  • ?*?Session?itself,?to?the?application,?and?SessionImplementor,?to?other?components ?
  • ?*?of?Hibernate.?This?class?is?not?threadsafe. ?
  • ?* ?
  • ?*?@author?Gavin?King ?
  • ?*/??
  • public?final?class?SessionImpl?extends?AbstractSessionImpl? ??
  • ????????implements?EventSource,?org.hibernate.classic.Session,?JDBCContext.Context?{ ??
  • ??????????//省略部分代碼 ??
  • ????//?save()?operations?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ??
  • ??
  • ????public?void?save(Object?obj,?Serializable?id)?throws?HibernateException?{ ??
  • ????????save(null,?obj,?id); ??
  • ????} ??
  • ????? ??
  • ????public?Serializable?save(Object?obj)?throws?HibernateException?{ ??
  • ????????return?save(null,?obj); ??
  • ????} ??
  • ??
  • ????public?Serializable?save(String?entityName,?Object?object)?throws?HibernateException?{ ??
  • ????????return?fireSave(?new?SaveOrUpdateEvent(entityName,?object,?this)?); ??
  • ????} ??
  • ??
  • ????public?void?save(String?entityName,?Object?object,?Serializable?id)?throws?HibernateException?{ ??
  • ????????fireSave(?new?SaveOrUpdateEvent(entityName,?object,?id,?this)?); ??
  • ????} ??
  • ??
  • ????private?Serializable?fireSave(SaveOrUpdateEvent?event)?{ ??
  • ????????errorIfClosed(); ??
  • ????????checkTransactionSynchStatus(); ??
  • ????????SaveOrUpdateEventListener[]?saveEventListener?=?listeners.getSaveEventListeners(); ??
  • ????????for?(?int?i?=?0;?i?<?saveEventListener.length;?i++?)?{ ??
  • ????????????saveEventListener[i].onSaveOrUpdate(event); ??
  • ????????} ??
  • ????????return?event.getResultId(); ??
  • ????} ??
  • ??????????//省略部分代碼 ??
  • }??
  • /*** Concrete implementation of a Session, and also the central, organizing component* of Hibernate's internal implementation. As such, this class exposes two interfaces;* Session itself, to the application, and SessionImplementor, to other components* of Hibernate. This class is not threadsafe.** @author Gavin King*/ public final class SessionImpl extends AbstractSessionImpl implements EventSource, org.hibernate.classic.Session, JDBCContext.Context {//省略部分代碼// save() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~public void save(Object obj, Serializable id) throws HibernateException {save(null, obj, id);}public Serializable save(Object obj) throws HibernateException {return save(null, obj);}public Serializable save(String entityName, Object object) throws HibernateException {return fireSave( new SaveOrUpdateEvent(entityName, object, this) );}public void save(String entityName, Object object, Serializable id) throws HibernateException {fireSave( new SaveOrUpdateEvent(entityName, object, id, this) );}private Serializable fireSave(SaveOrUpdateEvent event) {errorIfClosed();checkTransactionSynchStatus();SaveOrUpdateEventListener[] saveEventListener = listeners.getSaveEventListeners();for ( int i = 0; i < saveEventListener.length; i++ ) {saveEventListener[i].onSaveOrUpdate(event);}return event.getResultId();}//省略部分代碼 }



    持久化指定的游離態對象,首先要分配一個自動生成的主鍵標示符。(或者如果主鍵生成器正在使用,使用當前主鍵標示符屬性值)

    引用 請看進行了如下總結:
    一、在session的內部緩存中尋找保存對象,如果找到了,則認為此數據已經保存(曾經執行過insert操作),實體對象已經處于persistent狀態,直接返回。此時即使數據相比之前的狀態發生了變化,也將在事務提交時由臟數據檢查來判定是否需要執行update操作。

    二、如果實體對象實現了lifecycle接口,那么將執行待保存對象的onSave()方法。

    三、如果實體對象實現了Validatable接口,那么將會執行相應的validate()方法。

    四、如果存在攔截器對象,那么將會執行Interceptor.onSave()方法。

    五、構造insert SQL語句完成數據保存。

    六、數據保存成功后,設定實體對象的id為插入記錄的id。

    七、將保存后的實體對象納入Hibernate的內部緩存(一級緩存)。注意Hibernate不會把保存后的實體對象納入二級緩存,因為剛剛保存過的實體對象很可能在之后被修改,緩存的頻繁更新以及帶來的同步問題代價,超出了緩存該對象所帶來的收益。

    八、如果關聯關系映射配置了cascade="save-update"屬性,save操作對關聯對象級聯操作。



    ?

    引用
    update方法
    public void update(Object object)
    ??????????? throws HibernateException

    Update the persistent instance with the identifier of the given detached instance.
    If there is a persistent instance with the same identifier, an exception is thrown.
    This operation cascades to associated instances if the association is mapped with cascade="save-update".
    使用給定的游離狀態對象的主鍵標示符來更新持久化狀態實例對象。
    如果存在相同主鍵標示符的持久化狀態對象,拋出異常。
    如果關聯關系映射配置了cascade="save-update"屬性,update操作對關聯對象級聯操作。

    Parameters:
    object - a detached instance containing updated state
    包含了要更新狀態的游離狀態對象
    Throws:
    HibernateException



    Hibernate3.2中update()方法實現的源代碼:

    引用
    Java代碼 ?
  • /** ?
  • ?*?Concrete?implementation?of?a?Session,?and?also?the?central,?organizing?component ?
  • ?*?of?Hibernate's?internal?implementation.?As?such,?this?class?exposes?two?interfaces; ?
  • ?*?Session?itself,?to?the?application,?and?SessionImplementor,?to?other?components ?
  • ?*?of?Hibernate.?This?class?is?not?threadsafe. ?
  • ?* ?
  • ?*?@author?Gavin?King ?
  • ?*/??
  • public?final?class?SessionImpl?extends?AbstractSessionImpl? ??
  • ????????implements?EventSource,?org.hibernate.classic.Session,?JDBCContext.Context?{ ??
  • ??????????//省略部分代碼 ??
  • ????//?update()?operations?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ??
  • ??
  • ????public?void?update(Object?obj)?throws?HibernateException?{ ??
  • ????????update(null,?obj); ??
  • ????} ??
  • ??
  • ????public?void?update(Object?obj,?Serializable?id)?throws?HibernateException?{ ??
  • ????????update(null,?obj,?id); ??
  • ????} ??
  • ??
  • ????public?void?update(String?entityName,?Object?object)?throws?HibernateException?{ ??
  • ????????fireUpdate(?new?SaveOrUpdateEvent(entityName,?object,?this)?); ??
  • ????} ??
  • ??
  • ????public?void?update(String?entityName,?Object?object,?Serializable?id)?throws?HibernateException?{ ??
  • ????????fireUpdate(new?SaveOrUpdateEvent(entityName,?object,?id,?this)); ??
  • ????} ??
  • ??
  • ????private?void?fireUpdate(SaveOrUpdateEvent?event)?{ ??
  • ????????errorIfClosed(); ??
  • ????????checkTransactionSynchStatus(); ??
  • ????????SaveOrUpdateEventListener[]?updateEventListener?=?listeners.getUpdateEventListeners(); ??
  • ????????for?(?int?i?=?0;?i?<?updateEventListener.length;?i++?)?{ ??
  • ????????????updateEventListener[i].onSaveOrUpdate(event); ??
  • ????????} ??
  • ????} ??
  • ??????????//省略部分代碼 ??
  • }??
  • /*** Concrete implementation of a Session, and also the central, organizing component* of Hibernate's internal implementation. As such, this class exposes two interfaces;* Session itself, to the application, and SessionImplementor, to other components* of Hibernate. This class is not threadsafe.** @author Gavin King*/ public final class SessionImpl extends AbstractSessionImpl implements EventSource, org.hibernate.classic.Session, JDBCContext.Context {//省略部分代碼// update() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~public void update(Object obj) throws HibernateException {update(null, obj);}public void update(Object obj, Serializable id) throws HibernateException {update(null, obj, id);}public void update(String entityName, Object object) throws HibernateException {fireUpdate( new SaveOrUpdateEvent(entityName, object, this) );}public void update(String entityName, Object object, Serializable id) throws HibernateException {fireUpdate(new SaveOrUpdateEvent(entityName, object, id, this));}private void fireUpdate(SaveOrUpdateEvent event) {errorIfClosed();checkTransactionSynchStatus();SaveOrUpdateEventListener[] updateEventListener = listeners.getUpdateEventListeners();for ( int i = 0; i < updateEventListener.length; i++ ) {updateEventListener[i].onSaveOrUpdate(event);}}//省略部分代碼 }



    實例:
    前面我在實體對象狀態轉化部分曾經講過,session.update()方法能夠將一個處于游離狀態的對象,重新納入Hibernate的內部緩存,變成持久化對象。
    如下面的代碼:

    Java代碼 ?
  • Configuration?cfg?=?new?Configuration(); ??
  • SessionFactory?sf=cfg.?configure().buildSessionFactory(); ??
  • Customer?customer=new?Customer("關羽",27);//customer對象處于自由狀態 ??
  • Session?session=sf.openSession(); ??
  • //?開啟事務? ??
  • Transaction?tx=session.beginTransaction(); ??
  • //保存后customer對象處于持久化狀態 ??
  • session.save(customer); ??
  • //清空緩存后customer對象處于游離狀態 ??
  • session.flush(); ??
  • //?提交事務 ??
  • tx.commit(); ??
  • //session關閉 ??
  • session.close(); ??
  • ??
  • //?又開啟一個新的session? ??
  • Session?session2=sf.openSession(); ??
  • Transaction?tx2=session2.beginTransaction(); ??
  • //通過調用update()方法將游離狀態的customer對象,再次轉化成持久化狀態 ??
  • session2.update(customer); ??
  • //調用delete()方法后,當清空緩存時,會將customer對象移出緩存,同時會在數據庫中生成delete事務,來刪除customer對象對應的數據記錄 ??
  • session2.delete(customer); ??
  • tx.commit(); ??
  • session.close();??
  • Configuration cfg = new Configuration(); SessionFactory sf=cfg. configure().buildSessionFactory(); Customer customer=new Customer("關羽",27);//customer對象處于自由狀態 Session session=sf.openSession(); // 開啟事務 Transaction tx=session.beginTransaction(); //保存后customer對象處于持久化狀態 session.save(customer); //清空緩存后customer對象處于游離狀態 session.flush(); // 提交事務 tx.commit(); //session關閉 session.close();// 又開啟一個新的session Session session2=sf.openSession(); Transaction tx2=session2.beginTransaction(); //通過調用update()方法將游離狀態的customer對象,再次轉化成持久化狀態 session2.update(customer); //調用delete()方法后,當清空緩存時,會將customer對象移出緩存,同時會在數據庫中生成delete事務,來刪除customer對象對應的數據記錄 session2.delete(customer); tx.commit(); session.close();



    那么update方法到底執行了哪些步驟呢?它會按照下面的步驟進行操作:

    引用
    控制臺查看Hibernate生成的sql語句如下:
    Hibernate: select user0_.id as id0_0_, user0_.logon_name as logon2_0_0_, user0_.nick_name as nick3_0_0_, user0_.password as password0_0_ from logon_user user0_ where user0_.id=?
    Hibernate: update logon_user set logon_name=?, nick_name=?, password=? where id=?


    一、首先會在緩存中尋找需要更新的實體對象,如果找到就立刻返回,從這里我們可以看出如果對一個已經處于persistent的實體對象執行update()方法,將不會產生任何作用。
    二、然后當提交事務進行緩存清理時,將會通過臟數據檢查,確定變化的屬性,然后生成update SQL語句完成數據的更新。
    這里有一個問題我們要強調一下,那就是只要通過update()方法將一個游離對象與session相關聯,那么不論這個游離的實體對象的屬性是否發生改變,都會執行update SQL語句。
    如下面的代碼:

    Java代碼 ?
  • Transaction?tx=session.beginTransaction(); ??
  • session.update(customer); ??
  • tx.commit(); ??
  • session.close();??
  • Transaction tx=session.beginTransaction(); session.update(customer); tx.commit(); session.close();




    在這段代碼中并沒有修改customer對象的任何屬性值,但是也會執行一個update SQL語句,如果你希望在沒有改變實體對象屬性值的情況下不去執行update SQL語句,那么你要開啟實體對象元素的”select-before-update”屬性,將其設置為”true”,這個屬性默認為”false”。
    如下進行配置:
    如果啟用了這個屬性配置,那么在清理session緩存之前,會首先執行類似如下的一條SQL語句:
    Select * from logon_user where id='1';
    查詢處所有的customer實體在數據庫中對應的屬性值,然后逐條與緩存中屬性值進行比較,如果發生了改變,那么將會生成update操作進行數據更新,如果沒有發生改變那么將不會進行update操作。
    要跟據實際需求情況來決定是否開啟這個選項,如果實體對象的屬性不會經常發生改變,那么就應該開啟這個選項,以免執行多余的update操作。如果實體對象的屬性會經常發生改變,那么就沒必要開啟這個選項,以免在執行update操作前再執行多余的select語句。

    注意事項:
    1.當執行對一個游離實體對象執行session.update()操作時,如果在數據庫中不存在這個實體對應的紀錄,那么這個操作將會拋出異常。
    2.當執行session.update()方法將一個游離對象與session關聯時,如果此時在緩存中已經存在了與該實體對象具有相同OID的持久化對象,那么這個方法會拋出異常。
    如下面代碼:

    Java代碼 ?
  • Customer?customer1=new?Customer("劉備",25); ??
  • Session?session1=sf.openSession(); ??
  • Transaction?tx=session1.beginTransaction(); ??
  • //保存后customer對象處于持久化狀態 ??
  • session.save(customer1); ??
  • //清空緩存后customer對象處于游離狀態 ??
  • session.flush(); ??
  • tx.commit(); ??
  • session1.close(); ??
  • ? ??
  • Session?session2=sf.openSession(); ??
  • Transaction?tx2=session2.beginTransaction(); ??
  • Customer?othercustomer=(Customer)session2.load(Customer.class,"1"); ??
  • //通過調用update()方法將游離狀態的customer1對象,再次轉化成持久化狀態 ??
  • session2.update(customer1) ??
  • tx2.commit(); ??
  • session2.close();??
  • Customer customer1=new Customer("劉備",25); Session session1=sf.openSession(); Transaction tx=session1.beginTransaction(); //保存后customer對象處于持久化狀態 session.save(customer1); //清空緩存后customer對象處于游離狀態 session.flush(); tx.commit(); session1.close();Session session2=sf.openSession(); Transaction tx2=session2.beginTransaction(); Customer othercustomer=(Customer)session2.load(Customer.class,"1"); //通過調用update()方法將游離狀態的customer1對象,再次轉化成持久化狀態 session2.update(customer1) tx2.commit(); session2.close();


    當再次將游離對象customer1與session2關聯時,此時因為load()操作,在緩存已經加載了一個和customer1具有相同OID的othercustomer對象,此時由于Hibernate緩存的對象緩存機制不允許把OID相同的對象緩存,所以會拋出異常。

    引用
    load方法
    public void load(Object object,
    ???????????????? Serializable id)
    ????????? throws HibernateException

    Read the persistent state associated with the given identifier into the given transient instance.
    讀取和給定的主鍵標示符關聯的持久化狀態到給定的自由狀態的實例對象。
    Parameters:
    object - an "empty" instance of the persistent class
    id - a valid identifier of an existing persistent instance of the class
    object - 一個持久化類的空對象
    id - 一個已經存在的持久化實例對象的有效的主鍵標示符
    Throws:
    HibernateException



    ?

    引用
    get和load方法的區別?
    get和load方式是根據id取得一個記錄
    下邊詳細說一下get和load的不同,因為有些時候為了對比也會把find加進來。

    1.從返回結果上對比:
    load方式檢索不到的話會拋出org.hibernate.ObjectNotFoundException異常
    get方法檢索不到的話會返回null

    2.從檢索執行機制上對比:
    get方法和find方法都是直接從數據庫中檢索
    而load方法的執行則比較復雜
    ■ 首先查找session的persistent Context中是否有緩存,如果有則直接返回
    ■ 如果沒有則判斷是否是lazy,如果不是直接訪問數據庫檢索,查到記錄返回,查不到拋出異常
    ■ 如果是lazy則需要建立代理對象,對象的initialized屬性為false,target屬性為null
    ■ 在訪問獲得的代理對象的屬性時,檢索數據庫,如果找到記錄則把該記錄的對象復制到代理對象的target上,并將initialized=true,如果找不到就拋出異常 。

    3.根本區別說明
    ■ 如果你使用load方法,hibernate認為該id對應的對象(數據庫記錄)在數據庫中是一定存在的,所以它可以放心的使用,它可以放心的使用代理來延遲加載該對象。在用到對象中的其他屬性數據時才查詢數據庫,但是萬一數據庫中不存在該記錄,那沒辦法,只能拋異常。所說的load方法拋異常是指在使用該對象的數據時,數據庫中不存在該數據時拋異常,而不是在創建這個對象時(注意:這就是由于“延遲加載”在作怪)。

    由于session中的緩存對于hibernate來說是個相當廉價的資源,所以在load時會先查一下session緩存看看該id對應的對象是否存在,不存在則創建代理。所以如果你知道該id在數據庫中一定有對應記錄存在就可以使用load方法來實現延遲加載。

    ■ 對于get方法,hibernate會確認一下該id對應的數據是否存在,首先在session緩存中查找,然后在二級緩存中查找,還沒有就查數據庫,數據庫中沒有就返回null。

    對于load和get方法返回類型:雖然好多書中都這么說:“get()永遠只返回實體類”,但實際上這是不正確的,get方法如果在session緩存中找到了該id對應的對象,如果剛好該對象前面是被代理過的,如被load方法使用過,或者被其他關聯對象延遲加載過,那么返回的還是原先的代理對象,而不是實體類對象,如果該代理對象還沒有加載實體數據(就是id以外的其他屬性數據),那么它會查詢二級緩存或者數據庫來加載數據,但是返回的還是代理對象,只不過已經加載了實體數據。

    get方法首先查詢session緩存,沒有的話查詢二級緩存,最后查詢數據庫;反而load方法創建時首先查詢session緩存,沒有就創建代理,實際使用數據時才查詢二級緩存和數據庫。

    4.簡單總結

    總之對于get和load的根本區別,一句話,hibernate對于load方法認為該數據在數據庫中一定存在,可以放心的使用代理來延遲加載,如果在使用過程中發現了問題,只能拋異常;而對于get方法,hibernate一定要獲取到真實的數據,否則返回null。



    ?

    引用
    saveOrUpdate方法

    public void saveOrUpdate(Object object)
    ????????????????? throws HibernateException
    Either save(Object) or update(Object) the given instance, depending upon resolution of the unsaved-value checks (see the manual for discussion of unsaved-value checking).
    This operation cascades to associated instances if the association is mapped with cascade="save-update".
    可能對給定的實例對象執行save或者update方法,如果關聯關系映射配置了cascade="save-update"屬性,update操作對關聯對象級聯操作。

    Parameters:
    object - a transient or detached instance containing new or updated state
    object - 包含新的或者已更新狀態的自由態或者是游離態的
    對象實例
    Throws:
    HibernateException
    See Also:
    save(Object), update(Object)



    Hibernate3.2中saveOrUpdate()方法實現的源代碼:

    引用
    Java代碼 ?
  • /** ?
  • ?*?Concrete?implementation?of?a?Session,?and?also?the?central,?organizing?component ?
  • ?*?of?Hibernate's?internal?implementation.?As?such,?this?class?exposes?two?interfaces; ?
  • ?*?Session?itself,?to?the?application,?and?SessionImplementor,?to?other?components ?
  • ?*?of?Hibernate.?This?class?is?not?threadsafe. ?
  • ?* ?
  • ?*?@author?Gavin?King ?
  • ?*/??
  • public?final?class?SessionImpl?extends?AbstractSessionImpl? ??
  • ????????implements?EventSource,?org.hibernate.classic.Session,?JDBCContext.Context?{ ??
  • ??????????//省略部分代碼 ??
  • ????//?saveOrUpdate()?operations?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ??
  • ??
  • ????public?void?saveOrUpdate(Object?object)?throws?HibernateException?{ ??
  • ????????saveOrUpdate(null,?object); ??
  • ????} ??
  • ??
  • ????public?void?saveOrUpdate(String?entityName,?Object?obj)?throws?HibernateException?{ ??
  • ????????fireSaveOrUpdate(?new?SaveOrUpdateEvent(entityName,?obj,?this)?); ??
  • ????} ??
  • ??
  • ????private?void?fireSaveOrUpdate(SaveOrUpdateEvent?event)?{ ??
  • ????????errorIfClosed(); ??
  • ????????checkTransactionSynchStatus(); ??
  • ????????SaveOrUpdateEventListener[]?saveOrUpdateEventListener?=?listeners.getSaveOrUpdateEventListeners(); ??
  • ????????for?(?int?i?=?0;?i?<?saveOrUpdateEventListener.length;?i++?)?{ ??
  • ????????????saveOrUpdateEventListener[i].onSaveOrUpdate(event); ??
  • ????????} ??
  • ????} ??
  • ??????????//省略部分代碼 ??
  • }??
  • /*** Concrete implementation of a Session, and also the central, organizing component* of Hibernate's internal implementation. As such, this class exposes two interfaces;* Session itself, to the application, and SessionImplementor, to other components* of Hibernate. This class is not threadsafe.** @author Gavin King*/ public final class SessionImpl extends AbstractSessionImpl implements EventSource, org.hibernate.classic.Session, JDBCContext.Context {//省略部分代碼// saveOrUpdate() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~public void saveOrUpdate(Object object) throws HibernateException {saveOrUpdate(null, object);}public void saveOrUpdate(String entityName, Object obj) throws HibernateException {fireSaveOrUpdate( new SaveOrUpdateEvent(entityName, obj, this) );}private void fireSaveOrUpdate(SaveOrUpdateEvent event) {errorIfClosed();checkTransactionSynchStatus();SaveOrUpdateEventListener[] saveOrUpdateEventListener = listeners.getSaveOrUpdateEventListeners();for ( int i = 0; i < saveOrUpdateEventListener.length; i++ ) {saveOrUpdateEventListener[i].onSaveOrUpdate(event);}}//省略部分代碼 }
    查看onSaveOrUpdate(event)方法的定義:
    Java代碼 ?
  • public?class?DefaultSaveOrUpdateEventListener?extends?AbstractSaveEventListener?implements?SaveOrUpdateEventListener?{ ??
  • ??
  • ????private?static?final?Log?log?=?LogFactory.getLog(?DefaultSaveOrUpdateEventListener.class?); ??
  • ??
  • ????/** ?
  • ?????*?Handle?the?given?update?event. ?
  • ?????* ?
  • ?????*?@param?event?The?update?event?to?be?handled. ?
  • ?????*/??
  • ????public?void?onSaveOrUpdate(SaveOrUpdateEvent?event)?{ ??
  • ????????final?SessionImplementor?source?=?event.getSession(); ??
  • ????????final?Object?object?=?event.getObject(); ??
  • ????????final?Serializable?requestedId?=?event.getRequestedId(); ??
  • ??
  • ????????if?(?requestedId?!=?null?)?{ ??
  • ????????????//assign?the?requested?id?to?the?proxy,?*before*? ??
  • ????????????//reassociating?the?proxy ??
  • ????????????if?(?object?instanceof?HibernateProxy?)?{ ??
  • ????????????????(?(?HibernateProxy?)?object?).getHibernateLazyInitializer().setIdentifier(?requestedId?); ??
  • ????????????} ??
  • ????????} ??
  • ??
  • ????????if?(?reassociateIfUninitializedProxy(?object,?source?)?)?{ ??
  • ????????????log.trace(?"reassociated?uninitialized?proxy"?); ??
  • ????????????//?an?uninitialized?proxy,?noop,?don't?even?need?to? ??
  • ????????????//?return?an?id,?since?it?is?never?a?save() ??
  • ????????} ??
  • ????????else?{ ??
  • ????????????//initialize?properties?of?the?event: ??
  • ????????????final?Object?entity?=?source.getPersistenceContext().unproxyAndReassociate(?object?); ??
  • ????????????event.setEntity(?entity?); ??
  • ????????????event.setEntry(?source.getPersistenceContext().getEntry(?entity?)?); ??
  • ????????????//return?the?id?in?the?event?object ??
  • ????????????event.setResultId(?performSaveOrUpdate(?event?)?); ??
  • ????????} ??
  • ??
  • ????} ??
  • ????//?省略部分代碼...?... ??
  • }??
  • public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener implements SaveOrUpdateEventListener {private static final Log log = LogFactory.getLog( DefaultSaveOrUpdateEventListener.class );/*** Handle the given update event.** @param event The update event to be handled.*/public void onSaveOrUpdate(SaveOrUpdateEvent event) {final SessionImplementor source = event.getSession();final Object object = event.getObject();final Serializable requestedId = event.getRequestedId();if ( requestedId != null ) {//assign the requested id to the proxy, *before* //reassociating the proxyif ( object instanceof HibernateProxy ) {( ( HibernateProxy ) object ).getHibernateLazyInitializer().setIdentifier( requestedId );}}if ( reassociateIfUninitializedProxy( object, source ) ) {log.trace( "reassociated uninitialized proxy" );// an uninitialized proxy, noop, don't even need to // return an id, since it is never a save()}else {//initialize properties of the event:final Object entity = source.getPersistenceContext().unproxyAndReassociate( object );event.setEntity( entity );event.setEntry( source.getPersistenceContext().getEntry( entity ) );//return the id in the event objectevent.setResultId( performSaveOrUpdate( event ) );}}// 省略部分代碼... ... }



    這個方法包含了save()方法和update()方法的特點,如果傳入該方法的是一個游離對象,那么這個方法就會執行update操作,如果傳入該方法的是一個自由對象,那么這個方法就會執行insert操作。
    這個方法幕后的工作原理如下:
    1.首先在緩存尋找,如果找到待保存的操作就直接返回。
    2.如果實體實現了攔截方法,那么就執行isUnsaved()方法,判斷實體對象狀態。
    3.如果實體處于自由狀態就執行save(),如果實體處于游離狀態那么就執行update()。

    這里存在一個問題,那就是Hibernate是怎樣判斷一個實體是處于游離態還是臨時狀態的?
    如果實體滿足下面的一個條件,就認為這個實體處于臨時狀態。
    Java對象的OID值為null。
    1.如果Java對象具有version屬性(可以了解并發加鎖部分)且為null。
    2.如果實體的設置了屬性unsaved-value,而且OID值與unsaved-value值相等。
    3.如果實體的version屬性設置了unsaved-value,并且version屬性的值與unsaved-value值相等。
    4.如果實體實現了Interceptor,而且Interceptor.isUnsaved()方法返回true。
    滿足這些條件中的一個,這個實體就被認為是臨時對象。

    Session.delete()方法:
    delete()方法用于從數據庫中刪除一個或一批實體所對應的數據,如果傳入的對象是持久化對象,那么當清理緩存時,就會執行delete操作。
    如果傳入的是游離對象,那么首先會使該對象與session相關聯,然后當清理緩存時,再執行delete操作。

    看如下代碼:

    Java代碼 ?
  • ? ??
  • Session?session=sessionFactory().openSession(); ??
  • Transaction?tx=session.beginTransaction(); ??
  • //加載持久態對象 ??
  • Customer?customer=(Customer)session.load(Customer.class,”1”); ??
  • //計劃執行一條delete語句 ??
  • session.delete(customer); ??
  • //清理緩存,執行一條delete語句 ??
  • tx.commit(); ??
  • //關閉session,這時將會把customer對象從緩存中刪除 ??
  • session.close();??
  • Session session=sessionFactory().openSession(); Transaction tx=session.beginTransaction(); //加載持久態對象 Customer customer=(Customer)session.load(Customer.class,”1”); //計劃執行一條delete語句 session.delete(customer); //清理緩存,執行一條delete語句 tx.commit(); //關閉session,這時將會把customer對象從緩存中刪除 session.close();



    如果上面的代碼中的customer對象是一個游離對象,那么當執行session.delete()方法時,會首先將游離的customer對象與session相關聯(轉換為持久態),然后再清理緩存時,再執行delete操作。
    如果你想一次刪除多條數據,那么可以采用一個重載的delete()方法:delete("from Customer c where c.id > '8'");這個方法可以刪除符合條件的所有數據。

    總結

    以上是生活随笔為你收集整理的Hibernate数据保存操作方法的原理对比的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。