Hibernate3.X 實踐總結

Hibernate3.X  實踐總結
 
Hibernate不是盞省油的燈,也不是想像的射來射去很簡單的事。有不少細節處理很差會讓你很不舒服的,這方面最突出的表如今兩方面:一是事務管理,是JTA事務仍是JDBC事務?幸好有了Spring和J2EE容器;二是胡亂映射,模型關係創建不合理或者錯誤致使,或者是映射策略和技術不過關致使。這樣的最終結果是拋出一堆HibernateException,摸不着頭腦。下面是我實踐中的一些總結做爲備忘錄寫出來。
 
參考的是最新的Hibernate 3.2.6GA API文檔,還吸取了Hibernate牛人(夏新)寫的書和翻譯中文開發手冊的精華。
 
一、Configuration/SessionFactory/Session
Configuration實例表明了一個應用程序中Java類型 到SQL數據庫映射的完整集合. Configuration被用來構建一個(不可變的 (immutable))SessionFactory.
SessionFactory是線程安全的,建立代價很高。
Session是非線程安全的,輕量級的。一個Session對應一個JDBC鏈接,
Session的connection()會獲取Session與之對應的數據庫鏈接Connection對象。
Session的功能就是操做對象的,這些對象和數據庫表有映射關係。
Session操做的對象是有狀態的,分三類:
 
自由狀態(transient): 未持久化,未與任何Session相關聯,數據庫表中沒有對應的記錄。
持久化狀態(persistent): 與一個Session相關聯,對應數據庫表中一條記錄。
遊離狀態(detached): 已經進行過持久化,但當前未與任何Session相關聯,數據庫表中曾經有一條記錄,如今還有沒有就不知道了。
 
遊離狀態的實例能夠經過調用save()、persist()或者saveOrUpdate()方法進行持久化。持久化實例能夠經過調用 delete()變成遊離狀態。經過get()或load()方法獲得的實例都是持久化狀態的。遊離狀態的實例能夠經過調用 update()、0saveOrUpdate()、lock()或者replicate()進行持久化。遊離或者自由狀態下的實例能夠經過調用merge()方法成爲一個新的持久化實例。
 
二、Session的save()/persist()/update()/saveOrUpdate()/merge()/delete()方法
save()方法將指定對象保存,插入表中一條數據;
persist()方法將指定對象保存,插入表中一條數據,我還沒發現它和save方法有什麼特別之處。
replicate()方法徹底使用給定對象各個屬性的值(包括標識id)來持久化給定的遊離狀態(Transient)的實體,很暴力啊,其中還須要指定存儲模式(有四種保存策略供選擇)。
update()方法將指定對象更新,更新表中一條數據;
saveOrUpdate()方法接收一個實體對象,根據實體對象的id判斷是否已經存在進行保存或更新操做,這樣保存和更新方法就統一了;
merge()方法將給定的對象的狀態複製到具備相同標識的持久化對象上。
delete()方法將指定對象刪除,刪除表中一條數據;
 
特別注意:爲了使用saveOrUpdate()方法,在由定義映射文件時,經過設定<id>標籤的unsaved-value="null"來判斷執行什麼操做: 當id屬性等於unsaved-value的值(在此爲null)時,則認爲尚未保存,應該執行保存操做,不然執行更新操做。這樣設定以後,可使用saveOrUpdate()方法來統一保存和更新的方法。
 
<id name="id" column="id" type="java.lang.Integer" unsaved-value="null">
    <generator class="native"/>
</id>
 
unsaved-value能夠設定的值有四個:
any:老是儲存
none:老是更新
null:id爲null時儲存(預設)
valid:id爲null或是指定值時儲存
 
三、Session的get()/load()方法
get()方法會老是查詢實體對象,不存在時候返回null;
load()方法也是獲取一個實體對象,不存在時候拋空指針異常。
 
四、Session的clear()/evict()方法
clear()方法清除Session級別緩存中的全部實體(包括各類狀態)對象,目的是釋放內存。
evict()方法清除Session級別緩存中的指定的實體(包括各類狀態)對象。
固然,Session關閉後,這些緩存也就不存在了,會等待JVM回收。
 
五、Session的flush()方法
flush()強制持久化Session緩存中的實體對象。通常還會調用clear()或evict(),目的是趕忙保存,釋放寶貴內存資源。
 
六、Session的commit()/rollback()方法
commit()方法用於提交Session上的事務,不然工做單元不會對數據庫產生影響。若是執行出現異常(也就是commit()失敗了),則以前的操做取消,執行rollback()可撤消以前的操做。
 
七、Session的close()/isOpen()/isConnected()/reconnect()方法
close()方法關閉Session所對應數據庫鏈接,與其相關聯的對象生命週期結束。
isOpen()方法檢查Session是否仍然打開,若是Session已經斷開,則可使用reconnect(Connection connection)來從新讓Session關聯一個JDBC鏈接。
isConnected()方法檢查當前Session是否處於鏈接狀態。
 
八、Criteria、DetchedCriteria和Query接口
Criteria和Query的實例都是和Session綁定的,其生命週期跟隨着Session結束而結束。
DetchedCriteria實例至關於一個SQL模板,目的是爲了複用。其中的getExecutableCriteria(session)方法接收一個Session對象,並與之綁定,返回一個Criteria對象。
 
九、Hibernate類的initialize()方法
initialize()方法強制Hibernate當即加載指定實體所關聯的對象和集合。Hibernate類中還有其餘幾個頗有用但不適很經常使用的方法。
 
十、映射文件中的lazy屬性
在Hibernate3中,class元素的lazy屬性默認是true,若是不須要,則須要顯示指定爲lazy="false",不然,操做load返回的對象會拋異常。另外Hibernate3中還能夠爲實體屬性指定lazy屬性。
 
十二、JDBC事務和JTA事務
Hibernate自己沒有事務管理功能,它依賴於JDBC或JTA的事務管理功能,在Hibernate配置文件中,若是不顯式指定Transaction的工廠類別屬性hibernate.transaction.factory_class的配置,則默認爲JDBC事務:
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>。
在經過SessionFactory獲取到Session後,與Session相關聯的JDBC Connection實例就被設定爲false。
 
特別注意:若是數據庫不支持事務,好比MySQL的MyISAM引擎的表就不支持事務,聲明事務也不會起做用。要使MySQL5的表支持事務,則能夠指定表的引擎類型爲InnoDB。若是是學習或者研究,目前最好仍是使用PostgreSQL 8.3或DB二、Oracle。
 
JDBC事務老是和一個數據庫鏈接(或一個Session)相關聯的。
JTA事務則能夠跨越多個數據鏈接(或多個Session),這些鏈接還能夠是不一樣數據庫的鏈接,JTA事務通常由容器進行管理。編程只要在多個操做單元的開始和結束定義JTA事務的邊界便可。
 
特別注意:若是使用了JTA事務,則不能再用在JDBC式的事務來管理每一個Session的操做,不然會出錯。爲了程序的的通用性,通常來講,都是使用JTA事務來構建應用,這使用任何環境。固然,也可使用事務代理爲每一個JDBC的操做方法加入事務控制。這樣也爲程序之後移植到JTA容器事務上帶來很大方便。其實如今可使用Spring的事務管理,與Hibernate結合的很是完美。
 
敬請關注,未完待續。。。
相關文章
相關標籤/搜索