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 : 三个整合