Hibernate多表设计及映射
1.多表设计
在开发中,前期进行需求分析,需求分析提供E–R图,根据ER图编写表结构。
表之间关系存在3种:一对多、多对多、一对一。(回顾)
一对多:1表(主表)必须主键 和 多表(从表)必须外键,主表的主键 与 从表外键 形成主外键关系
多对多:提供中间表(从表),提供2个字段(外键)分别对应两个主表。
一对一:???
面单对象描述 对象与对象 之间关系?【掌握】
一对多:客户和订单
private class Customer{
//一对多:一个客户 拥有 多个订单
private Set<Order> orderSet;
}
private class Order{
//多对一:多个订单 属于 一个客户
private Customer customer;
}
多对多:Student学生 和 Course课程
private class Student{
//多对多:多个学生(当前)学习 【不同课程】
private Set<Course> courseSet ...;
}
private class Course{
//多对多:多个课程 可以被 【不同学生】学习
private Set<Student> student = ...;
}
一对一:公司company 和 地址address
private class Company{
private Address address;
}
private class Address{
private Company company;
}
2.关联关系映射
2.1一对多实现【掌握】
2.1.1实现类
public class Customer {
private Integer cid;
private String cname;
//一对多:一个客户(当前客户) 拥有 【多个订单】
// * 需要容器存放多个值,一般建议Set (不重复、无序)
// * 参考集合:List、Map、Array等
// ** 建议实例化--使用方便
private Set<Order> orderSet = new HashSet<Order>();
}
public class Order {
private Integer xid;
private String price;
//多对一:多个订单属于【一个客户】
private Customer customer;
}
2.1.2配置文件
Customer.hbm.xml
<class name="com.itheima.b_onetomany.Customer" table="t_customer">
<id name="cid">
<generator class="native"></generator>
</id>
<property name="cname"></property>
<!-- 一对多:一个客户(当前客户) 拥有 【多个订单】 1 确定器 set <set> 2 name确定对象属性名 3 确定从表外键的名称 4 确定关系,及另一个对象的类型 注意: 在hibernate中可以只进行单向配置 每一个配置项都可以完整的描述彼此关系。 一般情况采用双向配置,双方都可以完成描述表与表之间关系。 -->
<!-- 一对多:一个客户(当前客户) 拥有 【多个订单】 -->
<set name="orderSet" cascade="delete-orphan">
<key column="customer_id"></key>
<one-to-many class="com.itheima.b_onetomany.Order"/>
</set>
</class>
Order.hbm.xml
<class name="com.itheima.b_onetomany.Order" table="t_order">
<id name="xid">
<generator class="native"></generator>
</id>
<property name="price"></property>
<!-- 多对一:多个订单属于【一个客户】 * name 确定属性名称 * class 确定自定义类型 * column 确定从表的外键名称 -->
<many-to-one name="customer" class="com.itheima.b_onetomany.Customer" column="customer_id"></many-to-one>
</class>
2.2一对多操作
2.2.1保存客户
@Test
public void demo01(){
// 1 创建客户,并保存客户--成功
Session session = factory.openSession();
session.beginTransaction();
Customer customer = new Customer();
customer.setCname("田志成");
session.save(customer);
session.getTransaction().commit();
session.close();
}
2.2.2保存订单
@Test
public void demo02(){
// 2 创建订单,保存订单--成功,外键为null
Session session = factory.openSession();
session.beginTransaction();
Order order = new Order();
order.setPrice("998");
session.save(order);
session.getTransaction().commit();
session.close();
}
2.2.3客户关联订单,只保存客户
@Test
public void demo03(){
// 3 创建客户和订单,客户关联订单,保存客户?
Session session = factory.openSession();
session.beginTransaction();
//1 客户和订单
Customer customer = new Customer();
customer.setCname("成成");
Order order = new Order();
order.setPrice("998");
//2 客户关联订单
customer.getOrderSet().add(order);
//3 保存客户
session.save(customer);
session.getTransaction().commit();
session.close();
}
2.2.4双向关联,使用inverse
@Test
public void demo04(){
// 4 创建客户和订单,客户关联订单,订单也关联客户,保存客户和订单?
// * 开发中优化程序 , n + 1 问题?
// ** 解决方案1:客户不关联订单 ,不建议
// ** 解决方案2:客户放弃对订单表外键值的维护。
// **** Customer.hbm.xml <set name="orderSet" inverse="true">
// ** inverse 将维护外键值的权利交予对象。相当于自己放弃。(反转)
Session session = factory.openSession();
session.beginTransaction();
//1 客户和订单
Customer customer = new Customer();
customer.setCname("成成");
Order order = new Order();
order.setPrice("998");
//2 客户关联订单
customer.getOrderSet().add(order);
//3 订单也关联客户
order.setCustomer(customer);
//4 保存客户
// * 1 save(order) -- insert --> 1,998 null
// * 2 订单管理客户,此时null --预留update --> 更新所有(正常设置)
// * 3 save(customer) -- insert --> 1,成成
// * 4 客户关联订单 --> 预留update --> 更新订单外键 (维护外键)
// * 5 提交commit --> 执行2 和 4
session.save(order);
session.save(customer);
session.getTransaction().commit();
session.close();
}
在一对多开发中,一方一般都放弃对外键值的维护。及
<set inverse="truen
2.3级联操作(读、理解)
2.3.1save-update 级联保存或更新
@Test
public void demo032(){
// 32 创建客户和订单,客户关联订单,保存客户? --抛异常
// ** 解决方案2:级联操作--级联保存或更新
// ** Customer.hbm.xml <set cascade="save-update">
// ** 在保存客户的同时,一并保存订单
Session session = factory.openSession();
session.beginTransaction();
//1 客户和订单
Customer customer = new Customer(); //瞬时态
customer.setCname("成成");
Order order = new Order(); //瞬时态
order.setPrice("998");
//2 客户关联订单
customer.getOrderSet().add(order);
//3 保存客户
session.save(customer); //持久态
// 关联操作都是持久态的,此时 持久态Customer 引用 一个 瞬时态的Order 抛异常
session.getTransaction().commit();
session.close();
}
2.3.2delete 级联删除
@Test
public void demo05(){
// 5 查询客户,并删除(持久态)
// 默认:当删除客户,默认将订单外键设置成null。
// 级联删除:删除客户时,并将客户的订单删除。
// ** Customer.hbm.xml <set name="orderSet" cascade="delete">
Session session = factory.openSession();
session.beginTransaction();
//查询到确定某个用户id为10
Customer customer = (Customer) session.get(Customer.class, 10);
session.delete(customer);
session.getTransaction().commit();
session.close();
}
2.3.3孤儿删除
一对多关系,存在父子关系。1表(主表)可以成为父表,多表(从表)也可以子表。
总结:
主表不能删除,从表已经引用(关联)的数据
从表不能添加,主表不存在的数据。
@Test
public void demo06(){
// 6 查询客户,并查询订单,解除客户和订单订单的关系
// * 默认:客户和订单解除关系后,外键被设置成null,此时订单就是孤儿。客户和订单都存在。
// * 孤儿删除(孤子删除),当订单称为孤儿,一并删除。客户仍存在。
Session session = factory.openSession();
session.beginTransaction();
//1 查询客户
Customer customer = (Customer) session.get(Customer.class, 9);
//2查询订单
Order order = (Order) session.get(Order.class, 8);
//3 解除关系
customer.getOrderSet().remove(order);
session.getTransaction().commit();
session.close();
}
2.3.4总结
save-update:A保存,同时保存B
delete:删除A,同时删除B,AB都不存在
delete-orphan:孤儿删除,解除关系,同时将B删除,A存在的。
如果需要配置多项,使用逗号分隔。
all : save-update 和 delete 整合
all-delete-orphan : 三个整合
over~~~
还没有评论,来说两句吧...