Hibernate 多表設計之一對多
示例:用戶表和訂單表關係爲一對多的關係,一個用戶可以有多個訂單,但是一個訂單隻能對應一個用戶
- Customer.java
在“一”的一方(Customer)用Set來保存所有訂單引用
public class Customer {
private Integer id;
private String name;
private Set<Order> orders = new HashSet<>();
// Get和Set 代碼略過
}
- Order.java
直接保存Customer 的引用
public class Order {
private Integer id;
private String orderName;
private Customer customer;
// Get和Set 代碼略過
}
ORM 映射文件表達一對多關係、多對一
用set節點來描述一對多
<set name="orders" inverse="false">
<key column="cid"></key>
<one-to-many class="Order"/>
</set>
key節點用來描述外鍵列名,one-to-many 指定引用Customer作爲外鍵的表所對應用java Bean 類 ,Set 中的Inverse 屬性代表“是否不維護外鍵”True 替表不維護,False 代表維護,只能在“一”的一方放棄維護
Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.longdenghui.one2many2">
<class name="Customer" table="t_customer">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<set name="orders" inverse="false">
<key column="cid"></key>
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
Order.hbm.xml 中使用
<many-to-one name="customer" column="cid"></many-to-one>
來描述多對一的關係
Order.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.longdenghui.one2many2">
<class name="Order" table="t_order">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="orderName" column="order_name"></property>
<many-to-one name="customer" column="cid"></many-to-one>
</class>
</hibernate-mapping>
測試
Configuration conf = new Configuration().configure();
Session session = conf.buildSessionFactory().openSession();
Transaction tr = session.beginTransaction();
Customer c1 = new Customer();
c1.setName("龍登輝");
Order o1 = new Order();
Order o2 = new Order();
o1.setOrderName("娃哈哈");
o2.setOrderName("洗衣粉");
// o1.setCustomer(c1);
// o2.setCustomer(c1);
c1.getOrders().add(o1);
c1.getOrders().add(o2);
session.save(c1);
session.save(o1);
session.save(o2);
tr.commit();
因爲在Cusotmer.hbm.xml 中寫了Inverse 屬性爲False 所以Customer 會維護外鍵,不用再寫下列兩行代碼
o1.setCustomer(c1);
o2.setCustomer(c1);
如是inverse 屬性爲False 爲True 則代表Customer 放棄維護外鍵,所以上列兩行代碼必須加上,不然在Order表中的外鍵就爲null了,
cascade 屬性(save-update | delete | delete-orphan | all | all-delete-orphan)
級聯保存或更新 使用cascade屬性值選用“save-update”在Order 表中保存 Cutomer 表的主鍵,所以刪Customer 表需要先刪除Order 表中的數據,而在Customer.hbm.xml 文件中設置了級聯刪除的話可以使用以下代碼直接刪除
Customer c = (Customer) session.get(Customer.class, 1);
session.delete(c);
save-update(級聯保存或更新)
在“多”的一方中保存或更新“一”的一方的引用時,Hibernate 會幫我們將這些變化同步到數據庫中。
delete-orphan 孤兒刪除
在“多“的一方中刪除所保存的“一”的一方的引用時,代表和Order表所對應的數據解除關係,Order 表中被解除關係的數據被稱爲孤兒,Hibernate 會自動將孤兒數據刪除。delete 級聯刪除
當調用session中的delete() 方法 ,想要刪除一個Customer(“一”的一方)對象時,Hibernate 會將“多”的一方保存的引用所對應的數據庫的數據刪除。all : save-update 和 delete 整合
all-delete-orphan : 三個整合