[ JAVA] 淺談hibernate與ORM

描述個人對hibernate的認知

hibernate與ORM的出現其實已經是好幾年前的事情了,這邊描述一下個人的認知。


正常提到hibernate就該想到ORM(Object Relational Mapping),ORM就是可以透過設定物件屬性與資料庫table欄位間對應的方式,使得程式設計師可以在不知道實際資料庫欄位的狀態下進行資料庫的操作。
使用ORM會有甚麼樣的好處呢?


1.table與欄位之類的名稱變動可以不影響程式
2.開發者可以決定資料物件的名稱


有時候table與欄位的名稱很難理解,但是又很難改變,透過ORM就能夠輕易改變程式設計師需要知道的名稱,避免開發過程中產生誤解。
hibernate的對應方式一般來講有兩種:(可能有直接用程式語法的吧,但就算有我也不會想用)
1.xml
XML是比較早的寫法,但是對應關係的替換上會比較容易。
假設一個系統要運用在不同的環境時(可能是不同客戶,也可能是測試與正式環境),只要改對應檔就好。
2.annotation
這是比較新的寫法,我個人也很喜歡這樣的寫法,主要是覺得撰寫上比較方便。


在良葛格的學習筆記中有提到3種hibernate的資料操作方式:
1.Criteria
2.HQL(Hibernate官方建議使用這種)
3.Native SQL


使用JDBC進行資料庫資料的操作是要先取得connection,而hibernate對資料庫的操作是要取得session,由session來管理connection。我曾經看過第4種寫法:「從session取得connection,用使用jdbc的方式來操作」,有人這樣用還跟我說hibernate很好用。
我覺得在多table查詢時使用Criteria會挺麻煩的,一般來說使用HQL會比較適當。因為可以把查詢結果轉成自訂的POJO(不是使用xml或annotation進行對應設定),在一些需要簡單統計(EX: sum、avg)的查詢功能時會很好用。但是HQL能做的還是很有限,其Function再怎樣都比不上SQL的強大,但是使用SQL的話很容易就變成跟ORM無關了,也就是失去了使用ORM的好處。所以我在查詢時會比較喜歡用Hibernate建議的HQL,在沒其他選擇是只有用SQL。使用Hibernate的話,資料庫的設計很重要,例如:該避免需要使用case when的情況(hibernate沒有case...when)。


交易管理的部分,我建議除非你對交易管理的設定非常熟,否則不要使用openSessionInView。我之前曾經碰過一個系統,因為交易管理上的問題,所以一個系統同時存在hibernate與Spring兩種寫法來存取資料庫。雖然以當時情況可以不用搞成這樣,但因為一些人的問題就變成這樣了。


Hibernate是很強大,在使用上也有好幾種寫法可以使用,每種寫法都有其優缺點與特性,我認為比較適當的做法是對這些寫法都有一定程度的了解,在遇到需求時選擇適當的寫法會比較好。


現在來舉個例吧
假設要對一個單一table做CRUD,我會用甚麼寫法呢?
1.新增:
使用session.save(),算是使用Native SQL的寫法,就算沒有設定insert的SQL語法也會自動執行新增物件。
使用這寫法的原因很簡單,因為其他寫法都不能做新增(囧)
2.查詢:
看複雜度而定,簡單的情況取單一物件可能用session.get()或session.load()
簡單取得全部資料的話會使用Criteria
比較複雜的情況會用HQL
要是再更複雜到無法用HQL的話,只有使用session.createSQLQuery()了
3.更新:
雖然可以直接取session進行更新,但那會全部欄位都更新,我會認為使用HQL會比較適當。
原因在於彈性,你無法事先知道使用者要更新那些欄位,當使用者執行更新的指令時,用程式判斷哪些欄位要被更新,接著用自己寫的程式組出需要的HQL語法,最後進行執行,這樣才能控制住只更新想更新的欄位。
4.刪除
一般情況我會直接用session.delete()來做,如果遇到情況比較複雜我會選擇HQL,更複雜會用SQL(但通常使用HQL就很夠了)


以上算是個人對Hibernate的理解與認知,其實我工作上沒怎麼用Hibernate做CRUD,最多做查詢。以上對CRUD的寫法是自己寫code練習hibernate時採用的寫法。