Session.get/load的區別:
      1.如果未能發現符合條件的記錄,get方法返回null,而load方法會拋出一個ObejctNotFoundException。
      2.Load方法可返回實體的代理類類型,而get方法永遠直接返回實體類。
      3.Load方法可以充分利用內部緩存和二級緩存中現有數據,而get方法則僅僅在內部緩存中進行數據查找,如沒有發現對應數據,將越過二級緩存,直接調用SQL完成數據讀取。

 

 



      Session.find/iterate的區別:
      find方法將執行Select SQL從數據庫中獲得所有符合條件的記錄并構造相應的實體對象,實體對象構建完畢之后,就將其納入緩存。它對緩存只寫不讀,因此無法利用緩存。
      iterate方法首先執行一條Select SQL以獲得所有符合查詢條件的數據id,隨即,iterate方法首先在本地緩存中根據id查找對應的實體對象是否存在,如果緩存中已經存在對應的數據,則直接以此數據對象作為查詢結果,如果沒有找到,再執行相應的Select語句獲得對應的庫表記錄(iterate方法如果執行了數據庫讀取操作并構建了完整的數據對象,也會將其查詢結果納入緩存)。


[實際的情況是,如果使用了iterate方法返回Iterator類型的查詢結果,那么你一旦關閉session,Iterator中的數據立即就會消失.而通過find得到的List則不會如此,我想大部分人的使用習慣都是操作完成后立即關閉session,很多公司也強制要求這樣做.
Iterator的另一個麻煩事是fail-fast,在多線程環境下,很容易產生.使用線程安全的List子類,則不會有這個問題]

 

 



      Query Cache產生作用的情況:
      1.完全相同的Select SQL重復執行。
      2.在兩次查詢之間,此Select SQL對應的庫表沒有發生過改變。

 

 



      Session.save方法的執行步驟:
      1.在Session內部緩存中尋找待保存對象。內部緩存命中,則認為此數據已經保存(執行過insert操作),實體對象已經處于Persistent狀態,直接返回。
      2.如果實體類實現了lifecycle接口,則調用待保存對象的onSave方法。
      3.如果實體類實現了validatable接口,則調用其validate()方法。
      4.調用對應攔截器的Interceptor.onSave方法(如果有的話)。
      5.構造Insert SQL,并加以執行。
      6.記錄插入成功,user.id屬性被設定為insert操作返回的新記錄id值。
      7.將user對象放入內部緩存。
      8.最后,如果存在級聯關系,對級聯關系進行遞歸處理。

 

 



      Session.update方法的執行步驟:
      1.根據待更新實體對象的Key,在當前session的內部緩存中進行查找,如果發現,則認為當前實體對象已經處于Persistent狀態,返回。
      2.初始化實體對象的狀態信息(作為之后臟數據檢查的依據),并將其納入內部緩存。注意這里Session.update方法本身并沒有發送Update SQL完成數據更新操作,Update SQL將在之后的Session.flush方法中執行,根據id更新所有的字段,如update user set name=?, password=? where id=?。

 

 


 

      Session.saveOrUpdate方法的執行步驟:
      1.首先在Session內部緩存中進行查找,如果發現則直接返回。
      2.執行實體類對應的Interceptor.isUnsaved方法(如果有的話),判斷對象是否為未保存狀態。
      3.根據unsaved-value判斷對象是否處于未保存狀態。
      4.如果對象未保存(Transient狀態),則調用save方法保存對象。
      5.如果對象為已保存(Detached狀態),調用update方法將對象與Session重新關聯。



Session.delete(E)
 E 由持久狀態/游離狀態 -->>自由狀態



Session.flush()

調用flush
1.直接調用Session.flush();
2.tx.commit();
//flush before commiting the transaction and closing the session
//Flushing is the process of synchronising the underlying persistent store with persistable state held in memory.



E1=Session.merge(E)
if E is transient instance,則insert數據庫,E狀態不變化,E1是一個持久化對象;
if E is detached instance,則重新load,變成persistent instance;
if E is persistent instance,則從緩存中選擇;

// Copy   the   state   of   the   given   object   onto   the   persistent   object   with   the   same   identifier.  
// If   there   is   no   persistent   instance   currently   associated   with   the   session,  it  will   be   loaded.   Return   the   persistent   instance.  
// If   the   given   instance   is   unsaved,   save   a   copy   of   and   return   it   as   a   newly   persistent   instance.   The   given   instance   does   not   become   associated   with   the   session.  
// This   operation   cascades   to   associated   instances   if   the   association   is   mapped   with   cascade="merge".



 Session.persist(E)

persist() is well defined. It makes a transient instance persistent. However,
it doesn't guarantee that the identifier value will be assigned to the persistent
instance immediately, the assignment might happen at flush time. The spec doesn't say
that, which is the problem I have with persist().

persist() also guarantees that it will not execute an INSERT statement if it is
called outside of transaction boundaries. This is useful in long-running conversations
with an extended Session/persistence context.A method like persist() is required.

save() does not guarantee the same, it returns an identifier, and if an INSERT
has to be executed to get the identifier (e.g. "identity" generator, not "sequence"),
this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is not good in a long-running conversation with an extended Session/persistence context."