Hibernate多表设计及映射

逃离我推掉我的手 2022-05-18 10:19 219阅读 0赞

1.多表设计
在开发中,前期进行需求分析,需求分析提供E–R图,根据ER图编写表结构。
表之间关系存在3种:一对多、多对多、一对一。(回顾)
这里写图片描述
一对多:1表(主表)必须主键 和 多表(从表)必须外键,主表的主键 与 从表外键 形成主外键关系

多对多:提供中间表(从表),提供2个字段(外键)分别对应两个主表。

一对一:???

面单对象描述 对象与对象 之间关系?【掌握】
一对多:客户和订单

  1. private class Customer{
  2. //一对多:一个客户 拥有 多个订单
  3. private Set<Order> orderSet;
  4. }
  5. private class Order{
  6. //多对一:多个订单 属于 一个客户
  7. private Customer customer;
  8. }

多对多:Student学生 和 Course课程

  1. private class Student{
  2. //多对多:多个学生(当前)学习 【不同课程】
  3. private Set<Course> courseSet ...;
  4. }
  5. private class Course{
  6. //多对多:多个课程 可以被 【不同学生】学习
  7. private Set<Student> student = ...;
  8. }

一对一:公司company 和 地址address

  1. private class Company{
  2. private Address address;
  3. }
  4. private class Address{
  5. private Company company;
  6. }

2.关联关系映射

2.1一对多实现【掌握】

2.1.1实现类

  1. public class Customer {
  2. private Integer cid;
  3. private String cname;
  4. //一对多:一个客户(当前客户) 拥有 【多个订单】
  5. // * 需要容器存放多个值,一般建议Set (不重复、无序)
  6. // * 参考集合:List、Map、Array等
  7. // ** 建议实例化--使用方便
  8. private Set<Order> orderSet = new HashSet<Order>();
  9. }
  10. public class Order {
  11. private Integer xid;
  12. private String price;
  13. //多对一:多个订单属于【一个客户】
  14. private Customer customer;
  15. }

2.1.2配置文件
Customer.hbm.xml

  1. <class name="com.itheima.b_onetomany.Customer" table="t_customer">
  2. <id name="cid">
  3. <generator class="native"></generator>
  4. </id>
  5. <property name="cname"></property>
  6. <!-- 一对多:一个客户(当前客户) 拥有 【多个订单】 1 确定器 set <set> 2 name确定对象属性名 3 确定从表外键的名称 4 确定关系,及另一个对象的类型 注意: 在hibernate中可以只进行单向配置 每一个配置项都可以完整的描述彼此关系。 一般情况采用双向配置,双方都可以完成描述表与表之间关系。 -->
  7. <!-- 一对多:一个客户(当前客户) 拥有 【多个订单】 -->
  8. <set name="orderSet" cascade="delete-orphan">
  9. <key column="customer_id"></key>
  10. <one-to-many class="com.itheima.b_onetomany.Order"/>
  11. </set>
  12. </class>

Order.hbm.xml

  1. <class name="com.itheima.b_onetomany.Order" table="t_order">
  2. <id name="xid">
  3. <generator class="native"></generator>
  4. </id>
  5. <property name="price"></property>
  6. <!-- 多对一:多个订单属于【一个客户】 * name 确定属性名称 * class 确定自定义类型 * column 确定从表的外键名称 -->
  7. <many-to-one name="customer" class="com.itheima.b_onetomany.Customer" column="customer_id"></many-to-one>
  8. </class>

这里写图片描述
2.2一对多操作

2.2.1保存客户

  1. @Test
  2. public void demo01(){
  3. // 1 创建客户,并保存客户--成功
  4. Session session = factory.openSession();
  5. session.beginTransaction();
  6. Customer customer = new Customer();
  7. customer.setCname("田志成");
  8. session.save(customer);
  9. session.getTransaction().commit();
  10. session.close();
  11. }

2.2.2保存订单

  1. @Test
  2. public void demo02(){
  3. // 2 创建订单,保存订单--成功,外键为null
  4. Session session = factory.openSession();
  5. session.beginTransaction();
  6. Order order = new Order();
  7. order.setPrice("998");
  8. session.save(order);
  9. session.getTransaction().commit();
  10. session.close();
  11. }

2.2.3客户关联订单,只保存客户

  1. @Test
  2. public void demo03(){
  3. // 3 创建客户和订单,客户关联订单,保存客户?
  4. Session session = factory.openSession();
  5. session.beginTransaction();
  6. //1 客户和订单
  7. Customer customer = new Customer();
  8. customer.setCname("成成");
  9. Order order = new Order();
  10. order.setPrice("998");
  11. //2 客户关联订单
  12. customer.getOrderSet().add(order);
  13. //3 保存客户
  14. session.save(customer);
  15. session.getTransaction().commit();
  16. session.close();
  17. }

这里写图片描述
2.2.4双向关联,使用inverse
这里写图片描述

  1. @Test
  2. public void demo04(){
  3. // 4 创建客户和订单,客户关联订单,订单也关联客户,保存客户和订单?
  4. // * 开发中优化程序 , n + 1 问题?
  5. // ** 解决方案1:客户不关联订单 ,不建议
  6. // ** 解决方案2:客户放弃对订单表外键值的维护。
  7. // **** Customer.hbm.xml <set name="orderSet" inverse="true">
  8. // ** inverse 将维护外键值的权利交予对象。相当于自己放弃。(反转)
  9. Session session = factory.openSession();
  10. session.beginTransaction();
  11. //1 客户和订单
  12. Customer customer = new Customer();
  13. customer.setCname("成成");
  14. Order order = new Order();
  15. order.setPrice("998");
  16. //2 客户关联订单
  17. customer.getOrderSet().add(order);
  18. //3 订单也关联客户
  19. order.setCustomer(customer);
  20. //4 保存客户
  21. // * 1 save(order) -- insert --> 1,998 null
  22. // * 2 订单管理客户,此时null --预留update --> 更新所有(正常设置)
  23. // * 3 save(customer) -- insert --> 1,成成
  24. // * 4 客户关联订单 --> 预留update --> 更新订单外键 (维护外键)
  25. // * 5 提交commit --> 执行2 和 4
  26. session.save(order);
  27. session.save(customer);
  28. session.getTransaction().commit();
  29. session.close();
  30. }

在一对多开发中,一方一般都放弃对外键值的维护。及

  1. <set inverse="truen

2.3级联操作(读、理解)

2.3.1save-update 级联保存或更新
这里写图片描述

  1. @Test
  2. public void demo032(){
  3. // 32 创建客户和订单,客户关联订单,保存客户? --抛异常
  4. // ** 解决方案2:级联操作--级联保存或更新
  5. // ** Customer.hbm.xml <set cascade="save-update">
  6. // ** 在保存客户的同时,一并保存订单
  7. Session session = factory.openSession();
  8. session.beginTransaction();
  9. //1 客户和订单
  10. Customer customer = new Customer(); //瞬时态
  11. customer.setCname("成成");
  12. Order order = new Order(); //瞬时态
  13. order.setPrice("998");
  14. //2 客户关联订单
  15. customer.getOrderSet().add(order);
  16. //3 保存客户
  17. session.save(customer); //持久态
  18. // 关联操作都是持久态的,此时 持久态Customer 引用 一个 瞬时态的Order 抛异常
  19. session.getTransaction().commit();
  20. session.close();
  21. }

2.3.2delete 级联删除
这里写图片描述

  1. @Test
  2. public void demo05(){
  3. // 5 查询客户,并删除(持久态)
  4. // 默认:当删除客户,默认将订单外键设置成null。
  5. // 级联删除:删除客户时,并将客户的订单删除。
  6. // ** Customer.hbm.xml <set name="orderSet" cascade="delete">
  7. Session session = factory.openSession();
  8. session.beginTransaction();
  9. //查询到确定某个用户id为10
  10. Customer customer = (Customer) session.get(Customer.class, 10);
  11. session.delete(customer);
  12. session.getTransaction().commit();
  13. session.close();
  14. }

2.3.3孤儿删除
一对多关系,存在父子关系。1表(主表)可以成为父表,多表(从表)也可以子表。
这里写图片描述
这里写图片描述
总结:
主表不能删除,从表已经引用(关联)的数据
从表不能添加,主表不存在的数据。
这里写图片描述

  1. @Test
  2. public void demo06(){
  3. // 6 查询客户,并查询订单,解除客户和订单订单的关系
  4. // * 默认:客户和订单解除关系后,外键被设置成null,此时订单就是孤儿。客户和订单都存在。
  5. // * 孤儿删除(孤子删除),当订单称为孤儿,一并删除。客户仍存在。
  6. Session session = factory.openSession();
  7. session.beginTransaction();
  8. //1 查询客户
  9. Customer customer = (Customer) session.get(Customer.class, 9);
  10. //2查询订单
  11. Order order = (Order) session.get(Order.class, 8);
  12. //3 解除关系
  13. customer.getOrderSet().remove(order);
  14. session.getTransaction().commit();
  15. session.close();
  16. }

2.3.4总结
save-update:A保存,同时保存B
delete:删除A,同时删除B,AB都不存在
delete-orphan:孤儿删除,解除关系,同时将B删除,A存在的。
如果需要配置多项,使用逗号分隔。

all : save-update 和 delete 整合
all-delete-orphan : 三个整合

over~~~

发表评论

表情:
评论列表 (有 0 条评论,219人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Hibernate关系映射之一对映射

    一、基本概述 在表中的一对多,是使用外键关联,通过一张表的一个键另一个表的外键来建立一多关系;而在类中表示为一个类中有一个集合属性包含对方类的很多对象,而在另一个类中,只包