1.Hibernate對象的三種狀態
sql
在Hibernate中有三種狀態,對它的深刻理解,才能更好的理解hibernate的運行機理,剛開始不太注意這些概念,後來發現它是重要的。對於理解hibernate,JVM和sql的關係有更好的理解。對於須要持久化的JAVA對象,在它的生命週期中有三種狀態,並且互相轉化。
數據庫
1, 臨時狀態(Transient):用new建立的對象,它沒有持久化,沒有處於Session中,處於此狀態的對象叫臨時對象; 緩存
2, 持久化狀態(Persistent):已經持久化,加入到了Session緩存中。如經過hibernate語句保存的對象。處於此狀態的對象叫持久對象; session
3, 遊離狀態(Detached):持久化對象脫離了Session的對象。如Session緩存被清空的對象。
特色:已經持久化,但不在Session緩存中。處於此狀態的對象叫遊離對象; 分佈式
×√ spa |
臨時狀態 hibernate (Transient) 線程 |
持久化狀態 代理 (Persistent) xml |
遊離狀態 (Detached) |
是否處於Session緩存中 |
× |
√ |
× |
數據庫中是否有對應記錄 |
× |
√ |
√ |
三種狀態的區別以下:
1. 當對象處於Transient時,只在內存中有一個對象,沒ID,並且在緩存和數據庫中沒有;
2. 當對象處於save以後,內存、緩存都存在,有ID,並且當對象commit後數據庫也存在;
3.當對象處於Detached時,內存、緩存、數據庫都存在,並有ID,只是處於託管狀態;
如圖:
遊離對象和臨時對象異同:
二者都不會被Session關聯,對象屬性和數據庫可能不一致;
遊離對象有持久化對象關閉Session而轉化而來,在內存中還有對象因此此時就變成遊離狀態了;
Hibernate和SQL的關係:
在操做了hibernate的方法如save()等後,並無直接生成sql語句,去操做數據庫,而是把這些更新存入Session中,只有Session緩存要被更新時,底層的sql語句才能執行,數據存入數據庫;
下面舉例說明:
一,Session.save(user)運行機理。
1,把User對象加入緩存中,使它變成持久化對象;
2,選用映射文件指定的標識生成ID;
3,在Session清理緩存時候執行:在底層生成一個insert sql語句,把對象存入數據庫;
注意:在你執行Session.save(user)後,在Session清理緩存前,若是你修改user對象屬性值,那麼最終存入數據庫的值將是最後修改的值;此過程當中ID不能被修改;
二,Session.delete(user)運行過程。
若是user是持久化對象,則執行刪除操做,一樣底層數據庫的執行條件是:在Session清理緩存時候;
若是user是遊離對象:
1,將user對象和Session關聯,使之成爲持久化對象;
2,而後按照user 是持久化對象的過程執行;
2. Session經常使用方法:
2. 1Session的兩個方法區分:
獲得Session的方法有以下兩個:
openSession :每次都是新的Session,而且要手動close
getCurrentSession:從上下文找,如已有那麼用已經有的Session,如沒有,建立新的;不須要手動close;
ps. 上下文具體指的是hibernate.cfg.xml中的current_session_context_class:
<property name=」current_session_context_class」>thread</property>
current_session_context_class有四個值,兩個是經常使用的:
thread:在線程裏找是否有已經存在的Session;(最經常使用)
jta:主要針對數據庫分佈式而用;(處理多個數據庫事務)
2.2 delete :
delete(Object arg0); 當對象處於Detached後咱們就可使用delete進行刪除其對象;
2.3 load :
ss2.load(Class arg0, Serializable arg1); 返回Object,強制轉換下就OK了。
arg0:指的是你從數據庫取出數據當成arg0類型處理;
arg1:指的是主鍵;
2.4. get :
ss2.load(Class arg0, Serializable arg1); 與Load方法同樣能夠實現取出數據的功能;
注意: load 和 get的區別!
2.4.1. load返回的只是代理對象,只有當你真正使用對象內容的時候纔會發出sql語句;而get則會直接從數據庫
加載,馬上發出sql語句,不會延遲;
2.4.2. 當使用不存在的數據時,load不會報錯,而get則確定會報錯;
2.5 update:
update(Object arg0); 此種狀況效率很低,由於默認將全部字段都進行更新;
so, 能夠從數據庫中獲取到其對象後,直接set改變須要設置的屬性,而後當session進行commit時,hibernate默
認同步數據庫,如發現一致,不會發update的sql語句進行更新,當不一致的時候纔會發sql的update的語句,固然
此時更新也是所有字段進行更新,效率仍然偏低;
若是須要單獨更新一個字段,方法以下:
2.5.1:修改註解(不靈活)當不須要更新時進行更新的屬性,使用註解@Column(updatable=false)
updatable默認爲true;
2.5.2: 使用xml配置文件的話,可使用dynamic-update
2.5.3: HQL(EJBQL) (推薦)
2.6 :saveOrUpdate:
saveOrUpdate(Object o); 自動選擇save仍是update;
2.7: clear:
clear(); 主要用於清除session的緩存;
2.8: flush(): flush(); 強制讓緩存內容與數據庫內容作同步,默認當session的commit時才同步;