1、對象關系映射
1-1、單向多對一關聯
產品和分類的關系:多個不同產品屬于同一種分類。
private Category category;
<many-to-one name="category" column="categoryId" not-null="true" />
1-2、一對多映射
private Set products = new HashSet();
<set name="products" <!--Category 中集合屬性名稱為 products-->
table="product" <!--集合屬性對應表的名稱為 product-->
schema="test" <!--表的 schema 名稱為 test-->
lazy="true" <!--此集合采用延時加載策略-->
inverse="true" <!--由關聯屬性的另一方作為關聯的主控方-->
cascade="delete" <!--采用級聯刪除,當 Category 被刪除時關聯的此集合內容也將被刪除-->
sort="natural" <!--自然排序集合內容-->
order-by="productId asc" <!--按 productId 字段升序排列集合內容-->
>
<key column="category_fk" />
<one-to-many class="petstore.domain.Product" />
</set>
1-3、繼承映射
2、Hibernate 操作對象
2-1、對象的三種狀態
● 瞬時態(Transient)--VO(Value Ojbect)
對象實例產生到被 JVM 垃圾回收為止并不受 Hibernate 框架管理。
● 持久態(Persistent)--PO(Persistent Ojbect)
對象實例被 Hibernate 框架管理,該對象可能是剛被保存的,或剛從數據庫中被加載的。Hibernate 會檢測處于持久態的對象任何改動,在當前操作單元執行完畢將對象與數據庫同步,即將對象的屬性保存到數據庫映射對應的字段中。簡單點說就是該實體對象與 session 發生關系,而且處于 session 的有效期內。
● 托管態(Detached)--VO(Value Ojbect)
與持久對象關聯的 Session 被關閉后,對象就變為托管的,可繼續被修改。托管對象如果重新關聯到某個新的 Session 上,會再次變為持久的,同時改動也將會被持久化到數據庫。這個期間的轉變過程可以看作是應用程序事務,即中間會給用戶思考時間的長時間運行的操作單元。
處于托管態對象具有與數據庫表記錄間的聯系(持久化標識,identifier)。
2-2、對象操作的應用程序接口
● 修改對象
對于已經持久化的對象,不需要調用某個特定的方法就可以實現修改持久化,因為 Hibernate 會自動調用 flush() 方法保證與數據庫的同步。
對于處于托管狀態的實例,Hibernate 通過提供 Session.update() 或 Session.merge() 方法,重新關聯托管實例。但是需要注意的是:如果具有持久化標識(identifier)的對象之前已經被另一個會話連接(secondSession)裝載了,應用程序關聯操作會發生異常。
使用 merge() 方法時,用戶不必考慮 session 的狀態,可隨時將修改保存到數據庫中。例如:Session 中存在相同標識的持久化實例時,Hibernate 便會根據用戶給出的對象狀態覆蓋原有的持久化實例的狀態。
另外,Hibernate 還提供了 saveOrUpdate()方法,它即可分配新持久化標識(identifier),保存瞬時(transient)對象,又可更新/重新關聯托管的(identifier)實例。
● 刪除對象
通過 HQL 語句,調用重載的 delete(),可以一次刪除多個對象。
session.delete("from Customer as c where c.customerId <3");
● 查詢對象
已知對象表示符值查詢
對象標識符未知查詢 HQL
根據某些特定條件查詢 QBC,Query By Criteria
按詳例查詢 QBE,Query By Example
調用數據庫查詢 native SQL
查詢條件參數 ? 查詢條件參數索引,由 0 開始。
查詢條件實名 :name
外置命名查詢
在映射文件定義查詢語句,將程序與查詢語句分離:
<query name="CategoryById"
<! [CDATA[
from Category c where c.categoryId>? ]]>
</query>
程序調用:
Query q = sess.getNamedQuery("CategoryById");
q.setLong(0, name);
List cats = q.List();
用 Query 提供的 iterate() 方法遍歷查詢結果,如果查詢的結果在 session 或二級緩存(second-level cache)中,那么使用 iterate() 方法可以得到更好的性能。
如果 JDBC 驅動支持可滾動的 ResuleSet,Query 接口可以使用 ScrollableResults,允許你在查詢結果中靈活移動(需要保持數據庫連接和游標 cursor 處于抑制打開狀態)。
ScrollableResults cates = q.scroll();
cates.first()
cates.scroll(5);
● cascade 和 inverse 級聯操作
inverse
只對 set,one-to-many(或 many-to-many)有效,對于 many-to-one,one-to-one 無效
對集合起整體作用
cascade
對關系標記都有效
對集合的一個元素起作用,如果集合為空,那么 cascade 不會引發關聯操作
作用時機:在 flush 時(commit 會自動執行 flush),hibernate 會自行判斷每個 set 是否有變化,對有變化的 set 執行相應的 SQL,if (inverse) return。即:cascade 在前,inverse 在后。
異常:
org.hibernate.exception.ConstraintViolationException: could not insert
原因是 category_fk 字段約束不能為空,而在新建的 Product 對象時插入了空值,而且關聯關系由 Caterogy 對象維持,而被關聯的 Product 對象不知道自己與哪個 Category 對象關聯。說到底就是 pro 對象的 categoryId 值為空。
posted on 2009-04-11 20:46
黃小二 閱讀(431)
評論(0) 編輯 收藏 所屬分類:
S/S2SH 、
J2EE 、
J2SE