這篇文章主要介紹“Hibernate關聯關系怎么實現”,在日常操作中,相信很多人在Hibernate關聯關系怎么實現問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Hibernate關聯關系怎么實現”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
一, 一對多的單向關聯關系
[@more@]
首先先建立Customer和Order類,代碼如下:
Customer類:
package mypack;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
public class Customer implements Serializable {
private Long id;
private String name;
public Customer(String name) {
this.name = name;
}
public Customer() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return new ToStringBuilder(this)
.append("id", getId())
.toString();
}
}
Order類:
package mypack;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
public class Order implements Serializable {
private Long id;
private String orderNumber;
private mypack.Customer customer;
public Order(String orderNumber, mypack.Customer customer) {
this.orderNumber = orderNumber;
this.customer = customer;
}
public Order() {
}
public Order(mypack.Customer customer) {
this.customer = customer;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getOrderNumber() {
return this.orderNumber;
}
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
public mypack.Customer getCustomer() {
return this.customer;
}
public void setCustomer(mypack.Customer customer) {
this.customer = customer;
}
public String toString() {
return new ToStringBuilder(this)
.append("id", getId())
.toString();
}
}
Customer和Order類的配置文件分別是Customer.hbm.xml和Order.hbm.xml
Customer.hbm.xml如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
<class name="mypack.Customer" table="CUSTOMERS" >
<id name="id" type="long" column="ID">
<generator class="increment"/>
id>
<property name="name" type="string" >
<column name="NAME" length="15" />
property>
class>
</hibernate-mapping>
Order.hbm.xml如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
<class name="mypack.Order" table="ORDERS">
<id name="id" type="long" column="ID">
<generator class="increment"/>
id>
<property name="orderNumber" type="string" >
<column name="ORDER_NUMBER" length="15" />
property>
<many-to-one
name="customer"
column="CUSTOMER_ID"
class="mypack.Customer"
not-null="true"
/>
class>
hibernate-mapping>
在Order.hbm.xml中<many-to-one>元素建立了Customer和ORDERS表的外鍵CUSTOMER_ID之間
的映射。
它包括如下屬性。
● name:設定待映射的持久化類的屬性名,此處為Order類的customer屬性。
● column:設定和持久化類的屬性對應的表的外鍵,此處為ORDERS表的外鍵CUSTOMER_ID。
● class:設定持久化類的屬性的類型,此處設定customer屬性為Customer類。
● not-null:如果為ture,表示customer屬性不能為null,默認為false。
接下來我們持久化一個Customer對象以及和他關聯的Order對象:
(以下代碼并非是完整代碼,只是簡單把邏輯列出)
Configuration config = new Configuration();
config.addClass(Customer.class)
. addClass(Order.class);
sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = null;
tx = session.beginTransaction();
Customer customer=new Customer("Jack");
session.save(customer);
Order order1=new Order("Jack_Order001",customer);
Order order2=new Order("Jack_Order002",customer);
session.save(order1);
session.save(order2);
tx.commit();
當我們要持久化一個Customer對象以及和他關聯的Order對象的時候一定要先建立Customer對象并持久化它,否則當創建Order持久對象的時候會拋出異常,如果把session.save(customer)
注銷將會在session.save(order1)拋出PropertyValueException異常。分析產生異常原因:在調用session.save(order1)方法之前,order1和customer對象都是臨時對象,臨時對象就是剛剛用new創建出來,但是還沒有持久會的對象,而Hibernate不會自動持久化order1關聯的customer對象,在數據庫中意味著僅僅向ORDERS表中插入了一條記錄,并且該記錄的CUSTOMER_ID字段為null,違反了數據庫完整性約束,因為不允許ORDERS表的CUSTOMER_ID字段為null。
從上面的例子可以看出當Hibernate持久化一個臨時對象時,在默認情況下,它不會自動持久化所關聯的其他臨時對象,所以會拋出PropertyValueException異常。如果希望當Hibernate持久化Order對象時自動持久化所關聯的Customer對象,可以把<many-to-one>的cascade屬性設為“save-update”,cascade屬性默認為“none”:
<many-to-one
name="customer"
column="CUSTOMER_ID"
class="mypack.Customer"
cascade=“save-update”
not-null="true"
/>
這樣就能夠在Hibernate持久化Order對象時自動持久化所關聯的Customer對象了。
二, 一對多的雙向關聯關系
我們依然使用前面的Customer和Order的例子,由于是雙向關聯,Order類代碼如上面一樣,由于Customer類中有Order的關聯對象,因此Customer類改為如下:
package mypack;
import java.io.Serializable;
import java.util.Set;
import org.apache.commons.lang.builder.ToStringBuilder;
public class Customer implements Serializable {
private Long id;
private String name;
private Set orders;
public Customer(String name, Set orders) {
this.name = name;
this.orders = orders;
}
public Customer() {
}
public Customer(Set orders) {
this.orders = orders;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Set getOrders() {
return this.orders;
}
public void setOrders(Set orders) {
this.orders = orders;
}
public String toString() {
return new ToStringBuilder(this)
.append("id", getId())
.toString();
}
}
如何在映射文件中映射集合類型的order屬性呢?由于在CUSTOMERS表中沒有直接與order屬性對應的字段,因此不能用<property>元素來映射order屬性,而是要使用<set>元素:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
<class name="mypack.Customer" table="CUSTOMERS" >
<id name="id" type="long" column="ID">
<generator class="increment"/>
</id>
<property name="name" type="string" >
<column name="NAME" length="15" />
</property>
<set
name="orders"
cascade="save-update"
>
<key column="CUSTOMER_ID" />
<one-to-many class="mypack.Order" />
</set>
</class>
</hibernate-mapping>
<set>元素還包含兩個子元素:<key>和<one-to-many>,<one-to-many>元素設定所關聯的持久化類,此處為Order類,<key>元素設定與所關聯的持久化對應的表的外鍵,此處為ORDERS表的CUSTOMERS_ID字段。
它包括如下屬性:
● <set>元素表明Customer類的orders屬性為java.util.Set集合類型。
● <one-to-many>表明orders集合中存放的是一組Order對象。
● <key>屬性表明ORDERS表通過外鍵CUSTOMERS_ID參照CUSTOMERS表。
● cascade 屬性取值為"save-update",表明當保存或更新Customer對象時,會級聯保存或更新orders集合中的所有Order對象。
接下來我們持久化一個Customer對象以及和他關聯的Order對象:
Session session = sessionFactory.openSession();
Transaction tx = null;
tx = session.beginTransaction();
Customer customer=new Customer("Tom",new HashSet());
Order order=new Order();
order.setOrderNumber("Tom_Order001");
order.setCustomer(customer);
customer.getOrders().add(order);
session.save(customer);
tx.commit();
當<set>元素的cascade屬性為"save-update"時,Hibernate在持久化Customer對象時,會自動持久化關聯的Order對象。
如果是加載持久化對象,然后再建立關聯關系,那又該怎么做呢?如下所示:
Session session = sessionFactory.openSession();
Transaction tx = null;
tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(2));
Order order=(Order)session.load(Order.class,new Long(2));
order.setCustomer(customer);
customer.getOrders().add(order);
tx.commit();
Hibernate會自動清理緩存中的所有持久化對象,按照持久化對象狀態改變來同步更新數據庫,Hibernate在清理以上Customer對象和Order對象時執行了以下兩條SQL語句:
update ORDERS set ORDER_NUMBER='Jack_Order001',CUSTOMER_ID=2 where ID=2;
update ORDERS set CUSTOMER_ID=2 where ID=2;
盡管只是修改了ORDERS表的一條記錄,但是以上SQL語句表明Hibernate執行了兩次update操作這是因為HIbernate根據內存中持久化對象的狀態變化來決定需要執行的SQL語句,order.setCustomer(customer)執行的相應SQL語句為:
update ORDERS set ORDER_NUMBER='Jack_Order001',CUSTOMER_ID=2 where ID=2;
customer.getOrders().add(order)執行的相應SQL語句為:
update ORDERS set CUSTOMER_ID=2 where ID=2;
重復執行對于的SQL語句會影響應用程序的性能,那么解決的辦法是把<set>元素的inverse屬性設置為true,默認為false:
<set
name="orders"
cascade="save-update"
inverse="ture"
>
<key column="CUSTOMER_ID" />
<one-to-many class="mypack.Order" />
set>
因此在映射一對多雙向關聯關系時,應該在"one"方把inverse屬性設為“ture”,這樣可以提高性能。
三,一對多雙向自身關聯關系
以食品為例,它代表商品類別,存在一對多雙向自身關聯關系。如下圖所示,水果類別屬于食品類別,同時它又包含兩個子類別:蘋果類別和桔子類別。
圖中每一種商品代表一個Category對象,這些對象形成了樹型數據結構。每個Category<span style="FONT-FAMILY:
到此,關于“Hibernate關聯關系怎么實現”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。