Hibernate多表设计和关联关系映射

来源:互联网 发布:插画师培训 知乎 编辑:程序博客网 时间:2024/06/13 10:50

多表设计

l  在开发中,前期进行需求分析,需求分析提供E--R图,根据ER图编写表结构。

l  表之间关系存在3种:一对多、多对多、一对一。、


一对多:1表(主表)必须主键 和 多表(从表)必须外键,主表的主键 与从表外键 形成主外键关系

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

 一对一:???


l  面单对象描述 对象与对象 之间关系?【掌握】

       一对多:客户和订单

              private class Customer{

                     //一对多:一个客户 拥有 多个订单

                     privateSet<Order> orderSet;

              }


              private class Order{

                     //多对一:多个订单 属于 一个客户

                     privateCustomer customer;

              }


       多对多:Student学生 和 Course课程

              private class Student{

                     //多对多:多个学生(当前)学习 【不同课程】

                     privateSet<Course> courseSet ...;

              }

              private class Course{  

                     //多对多:多个课程 可以被 【不同学生】学习

                     privateSet<Student> student = ...;

              }


       一对一:公司company 和 地址address

              private class Company{

                     privateAddress address;

              }

              private class Address{

                     privateCompany company;

              }


关联关系映射

一、一对多实现:

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、配置文件

l  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>


l  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>




二、一对多操作

1、保存客户

@Testpublic void demo01(){// 1 创建客户,并保存客户--成功Session session = factory.openSession();session.beginTransaction();Customer customer = new Customer();customer.setCname("田志成");session.save(customer);session.getTransaction().commit();session.close();}


2、保存订单

@Testpublic void demo02(){// 2 创建订单,保存订单--成功,外键为nullSession session = factory.openSession();session.beginTransaction();Order order = new Order();order.setPrice("998");session.save(order);session.getTransaction().commit();session.close();}


3、客户关联订单,只保存客户

@Testpublic 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();}


4、双向关联,使用inverse



@Testpublic 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();}


l  在一对多开发中,一方一般都放弃对外键值的维护。及<setinverse="true



三、级联操作

1、save-update 级联保存或更新



@Testpublic 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、delete级联删除



@Testpublic void demo05(){// 5 查询客户,并删除(持久态)// 默认:当删除客户,默认将订单外键设置成null。// 级联删除:删除客户时,并将客户的订单删除。// ** Customer.hbm.xml <set name="orderSet" cascade="delete">Session session = factory.openSession();session.beginTransaction();Customer customer = (Customer) session.get(Customer.class, 10);session.delete(customer);session.getTransaction().commit();session.close();}


3、孤儿删除

l  一对多关系,存在父子关系。1表(主表)可以成为父表,多表(从表)也可以子表。



总结:

              主表不能删除,从表已经引用(关联)的数据

              从表不能添加,主表不存在的数据。



@Testpublic 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();}


4、总结

save-update:A保存,同时保存B

delete:删除A,同时删除B,AB都不存在

delete-orphan:孤儿删除,解除关系,同时将B删除,A存在的。

如果需要配置多项,使用逗号分隔。<set cascade="save-update,delete">

 

all : save-update 和 delete 整合

all-delete-orphan : 三个整合




0 0
原创粉丝点击