設計細顆粒度的持久類而且使用<component>來實現映射。
例如使用一個Address持久類來封裝 street, suburb, state, postcode. 這將有利於代碼重用和簡化代碼重構(refactoring)的工做。
對持久類聲明標識符屬性( identifier properties)。
Hibernate中標識符屬性是可選的,不過有不少緣由來講明你應該使用標識符屬性。咱們建議標識符應該是「人造」的(自動生成,不涉及業務含義)。
使用天然鍵(natural keys)標識
對全部的實體都標識出天然鍵,用<natural-id>進行映射。實現equals()和hashCode(),在其中用組成天然鍵的屬性進行比較。
爲每一個持久類寫一個映射文件
不要把全部的持久類映射都寫到一個大文件中。把 com.eg.Foo 映射到com/eg/Foo.hbm.xml中, 在團隊開發環境中,這一點顯得特別有意義。
把映射文件做爲資源加載
把映射文件和他們的映射類放在一塊兒進行部署。
考慮把查詢字符串放在程序外面
若是你的查詢中調用了非ANSI標準的SQL函數,那麼這條實踐經驗對你適用。把查詢字符串放在映射文件中可讓程序具備更好的可移植性。
使用綁定變量
就像在JDBC編程中同樣,應該老是用佔位符"?"來替換很是量值,不要在查詢中用字符串值來構造很是量值!更好的辦法是在查詢中使用命名參數。
不要本身來管理JDBC connections
Hibernate容許應用程序本身來管理JDBC connections,可是應該做爲最後沒有辦法的辦法。若是你不能使用Hibernate內建的connections providers,那麼考慮實現本身來實現org.hibernate.connection.ConnectionProvider
考慮使用用戶自定義類型(custom type)
假設你有一個Java類型,來自某些類庫,須要被持久化,可是該類沒有提供映射操做須要的存取方法。那麼你應該考慮實現org.hibernate.UserType接口。這種辦法使程序代碼寫起來更加自如,再也不須要考慮類與Hibernate type之間的相互轉換。
在性能瓶頸的地方使用硬編碼的JDBC
在系統中對性能要求很嚴格的一些部分,某些操做也許直接使用JDBC會更好。可是請先確認這的確是一個瓶頸,而且不要想固然認爲JDBC必定會更快。若是確實須要直接使用JDBC,那麼最好打開一個 Hibernate Session 而後從 Session得到connection,按照這種辦法你仍然可使用一樣的transaction策略和底層的connection provider。
理解Session清洗( flushing)
Session會不時的向數據庫同步持久化狀態,若是這種操做進行的過於頻繁,性能會受到必定的影響。有時候你能夠經過禁止自動flushing,儘可能最小化非必要的flushing操做,或者更進一步,在一個特定的transaction中改變查詢和其它操做的順序。
在三層結構中,考慮使用託管對象(detached object)
當使用一個servlet / session bean 類型的架構的時候, 你能夠把已加載的持久對象在session bean層和servlet / JSP 層之間來回傳遞。使用新的session來爲每一個請求服務,使用 Session.merge() 或者Session.saveOrUpdate()來與數據庫同步。
在兩層結構中,考慮使用長持久上下文(long persistence contexts).
爲了獲得最佳的可伸縮性,數據庫事務(Database Transaction)應該儘量的
短。可是,程序經常須要實現長時間運行的「應用程序事務(Application
Transaction)」,包含一個從用戶的觀點來看的原子操做。這個應用程序事務
可能跨越屢次從用戶請求到獲得反饋的循環。用脫管對象(與session脫離的對
象)來實現應用程序事務是常見的。或者,尤爲在兩層結構中,把Hibernate
Session從JDBC鏈接中脫離開,下次須要用的時候再鏈接上。毫不要把一個
Session用在多個應用程序事務(Application Transaction)中,不然你的數據
可能會過時失效。
不要把異常當作可恢復的
這一點甚至比「最佳實踐」還要重要,這是「必備常識」。當異常發生的時
候,必需要回滾 Transaction ,關閉Session。若是你不這樣作的話,
Hibernate沒法保證內存狀態精確的反應持久狀態。尤爲不要使用
Session.load()來判斷一個給定標識符的對象實例在數據庫中是否存在,應該
使用Session.get()或者進行一次查詢.
對於關聯優先考慮lazy fetching
謹慎的使用主動抓取(eager fetching)。對於關聯來講,若其目標是沒法在第二級緩存中徹底緩存全部實例的類,應該使用代理(proxies)與/或具備延遲加載屬性的集合(lazy collections)。若目標是能夠被緩存的,尤爲是緩存的命中率很是高的狀況下,應該使用lazy="false",明確的禁止掉eager fetching。若是那些特殊的確實適合使用join fetch 的場合,請在查詢中使用left join fetch。
使用open session in view模式,或者執行嚴格的裝配期(assembly phase)策略來避免再次抓取數據帶來的問題
Hibernate讓開發者們擺脫了繁瑣的Data Transfer Objects (DTO)。在傳統的EJB結構中,DTO有雙重做用:首先,他們解決了entity bean沒法序列化的問題;其次,他們隱含地定義了一個裝配期,在此期間,全部在view層須要用到的數據,都被抓取、集中到了DTO中,而後控制才被裝到表示層。Hibernate終結了第一個做用。然而,除非你作好了在整個渲染過程當中都維護一個打開的持久化上下文(session)的準備,你仍然須要一個裝配期(想象一下,你的業務方法與你的表示層有嚴格的契約,數據老是被放置到託管對象中)。這並不是是Hibernate的限制!這是實現安全的事務化數據訪問的基本需求。
考慮把Hibernate代碼從業務邏輯代碼中抽象出來
把Hibernate的數據存取代碼隱藏到接口(interface)的後面,組合使用DAO和Thread Local Session模式。經過Hibernate的UserType,你甚至能夠用硬編碼的JDBC來持久化那些本該被Hibernate持久化的類。 (該建議更適用於規模足夠大應用軟件中,對於那些只有5張表的應用程序並不適合。)不要用怪異的鏈接映射
多對多鏈接用得好的例子實際上至關少見。大多數時候你在「鏈接表」中須要保存額外的信息。這種狀況下,用兩個指向中介類的一對多的鏈接比較好。實際上,咱們認爲絕大多數的鏈接是一對多和多對一的,你應該謹慎使用其它鏈接風格,用以前問本身一句,是否真的必須這麼作。
偏心雙向關聯
單向關聯更加難於查詢。在大型應用中,幾乎全部的關聯必須在查詢中能夠雙向導航。