06-Hibernate中一对多,多对一,多对多分别在数据库表,对象entity,以及xml文件中的表达
-
一对多|多对一
- 关系表达
-
表中的表达
- 在表中的表达,例如客户对联系人,客户是一的一方,联系人是多的一方,也就是一个客户下可以有多个联系人,而多个联系人对应一个客户,所以客户对联系人就是一对多的关系,联系人对客户就是多对一的关系,数据库表中在多的一方使用外键表示关联关系。(详情请参考图片)
- 在表中的表达,例如客户对联系人,客户是一的一方,联系人是多的一方,也就是一个客户下可以有多个联系人,而多个联系人对应一个客户,所以客户对联系人就是一对多的关系,联系人对客户就是多对一的关系,数据库表中在多的一方使用外键表示关联关系。(详情请参考图片)
-
实体中的表达
- 在实体中的表达,例如客户对联系人,在一的一方创建私有的联系人set集合并new出来(new出来的作用就是方便后面传参),在多的一方创建私有的客户对象。(详情请参考图片)
- 在实体中的表达,例如客户对联系人,在一的一方创建私有的联系人set集合并new出来(new出来的作用就是方便后面传参),在多的一方创建私有的客户对象。(详情请参考图片)
-
对象关系映射配置文件中的表达
-
在xxx.hbm.xml配置文件中,例如客户对联系人,在(客户)方创建一个set标签,name属性为实体文件中创建的set集合,inverse属性为性能优化,提高关系维护的性能,cascade属性为级联操作,简化操作,省代码;set标签下的key标签,column属性为外键列名;set标签下的one-to-many标签,class属性为关联的对象的完整类名
<!-- 集合,一对多关系,在配置文件中配置 --> <!-- name属性:集合属性 column属性:外键列名 class属性:填写与我关联的对象完整类名 --> <!-- 级联操作:cascade save-update:级联保存更新 delete:级联删除。 all:save-update+delete 级联操作:简化操作.目的就是少写2行代码而已。 --> <!-- inverse属性:配置关系是否维护。 true:当前配置的customer是不维护关系, false(默认值):customer维护关系 inverse属性:性能优化,提高关系维护的性能。 原则:无论怎么放弃,总有一个必须要维护, 一对多关系中:一的一方放弃,也只能一的一方放弃,多的一方不能放弃的。 --> <set name="linkMens" inverse="true" cascade="delete"> <key column="lkm_cust_id"></key> <one-to-many class="LinkMan"/> </set>
-
在xxx.hbm.xml配置文件中,例如客户对联系人,在(联系人)方创建一个many-to-one标签,name属性就是创建的客户对象名称,column属性是外键列名,class属性与我关联的对象的完整类名(客户)。
<!-- 多对一 --> <!-- name属性:引用属性名 column属性:外键列名 class属性:与我关联的对象完整类名 --> <!-- 级联操作:cascade save-update:级联保存更新 delete:级联删除。 all:save-update+delete 级联操作:简化操作.目的就是少写2行代码而已。 --> <!-- 多的一方:不能放弃维护关系的,外键字段就在多的一方。 --> <many-to-one name="customer" column="lkm_cust_id" class="Customer" ></many-to-one>
-
-
一对多,多对一在实际中的操作
@Test //保存客户,以及客户下的联系人 public void fun1(){ //1.获得session Session session = HibernateUtils.openSession(); //2.开启事务 Transaction tx = session.beginTransaction(); //---------------------------------------------- //3.操作 Customer c = new Customer(); c.setCust_name("潭州教育"); LinkMan lm1 = new LinkMan(); lm1.setLkm_name("清子"); LinkMan lm2 = new LinkMan(); lm2.setLkm_name("好人"); //开始表达关系 //一对多,客户下有2个联系人,清子和好人 c.getLinkMans().add(lm1); c.getLinkMans().add(lm2); //多对一,练习人属于哪个客户 lm1.setCustomer(c); lm2.setCustomer(c); //执行保存操作,将瞬时状态的对象转化为持久化状态 session.save(c); session.save(lm1); session.save(lm2); //---------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
@Test //为客户添加联系人 public void fun2(){ //1.获得session Session session = HibernateUtils.openSession(); //2.开启事务 Transaction tx = session.beginTransaction(); //---------------------------------------------- //3.操作 //1.获得要操作的客户对象 Customer c = session.get(Customer.class, 1L); //2.创建联系人 LinkMan lm1 = new LinkMan(); lm1.setLkm_name("金千亿"); //3.将联系人添加到客户,将客户设置到联系人中 c.getLinkMans().add(lm1); lm1.setCustomer(c); //4.执行保存 session.save(lm1); //---------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
@Test //为客户删除联系人 public void fun3(){ //1.获得session Session session = HibernateUtils.openSession(); //2.开启事务 Transaction tx = session.beginTransaction(); //---------------------------------------------- //3.操作 //1.获取要操作的对象 Customer c = session.get(Customer.class, 1l); //2.获得要移除的联系人 LinkMan lm1 = session.get(LinkMan.class, 1l); //3.将联系人从客户集合中删除 c.getLinkMans().remove(lm1); lm1.setCustomer(null); //---------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
-
测试级联保存
@Test //保存客户,以及客户下的联系人 //cascade:save-update public void fun1(){ //1.获得session Session session = HibernateUtils.openSession(); //2.开启事务 Transaction tx = session.beginTransaction(); //---------------------------------------------- //3.操作 Customer c = new Customer(); c.setCust_name("潭州教育"); LinkMan lm1 = new LinkMan(); lm1.setLkm_name("清子"); LinkMan lm2 = new LinkMan(); lm2.setLkm_name("好人"); //开始表达关系 //一对多,客户下有2个联系人,清子和好人 c.getLinkMans().add(lm1); c.getLinkMans().add(lm2); //多对一,练习人属于哪个客户 lm1.setCustomer(c); lm2.setCustomer(c); //执行保存操作,将瞬时状态的对象转化为持久化状态 session.save(c); //使用了级联保存,这里就可以不用保存后面两条了 //session.save(lm1); //session.save(lm2); //---------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
@Test //测试删除客户时,级联删除(解除)客户下的联系人 //cascade:delete public void fun2(){ //1.获得session Session session = HibernateUtils.openSession(); //2.开启事务 Transaction tx = session.beginTransaction(); //---------------------------------------------- //3.操作 //1.获取要操作的对象 Customer c = session.get(Customer.class, 1l); //2.调用delete删除(接触)客户 session.delete(c); //---------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
@Test //保存联系人以及联系人对应的客户 //cascade:save-update public void fun3(){ //1.获得session Session session = HibernateUtils.openSession(); //2.开启事务 Transaction tx = session.beginTransaction(); //---------------------------------------------- //3.操作 Customer c = new Customer(); c.setCust_name("tz"); LinkMan lm1 = new LinkMan(); lm1.setLkm_name("老二"); //一对多,客户下有多个联系人 c.getLinkMans().add(lm1); //表达多对一,联系人属于哪个客户 lm1.setCustomer(c); //这里要保存一的一方,不能保存多的一方,否则报错,这里是报错的 session.save(lm1); //---------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
-
操作进阶–关系维护属性
@Test //保存客户,以及客户下的联系人 //cascade:save-update public void fun1(){ //1.获得session Session session = HibernateUtils.openSession(); //2.开启事务 Transaction tx = session.beginTransaction(); //---------------------------------------------- //3.操作 Customer c = new Customer(); c.setCust_name("哈哈哈哈"); LinkMan lm1 = new LinkMan(); lm1.setLkm_name("清子"); LinkMan lm2 = new LinkMan(); lm2.setLkm_name("好人"); //一对多,客户下有多个联系人 //如果咱们的客户放弃维护与联系人的关系,维护关系的代码可以省略 //c.getLinkMans().add(lm1); //c.getLinkMans().add(lm2); //多对一,联系人属于哪个客户 lm1.setCustomer(c); lm2.setCustomer(c); //执行保存操作,将瞬时状态的对象转化为持久化状态 session.save(c); session.save(lm1); session.save(lm2); //---------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
@Test //为客户删除联系人 //cascade:save-update public void fun2(){ //1.获得session Session session = HibernateUtils.openSession(); //2.开启事务 Transaction tx = session.beginTransaction(); //---------------------------------------------- //3.操作---当cascade:save-update,如果客户放弃维护关系的话,在删除的时候,就无法通过删除客户来删除数据了 Customer c = session.get(Customer.class, 1l); session.delete(c); //---------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
-
- 关系表达
-
多对多
-
关系表达
-
在表中的表达,例如员工表和角色表中,一个员工在公司可以有多种角色,一个角色也可以由多名员工承担,所以员工表和角色表是多对多的关系,在数据库表中,使用第三张表(中间表)来表示,中间表至少有两列,都是外键分别引用,两张表的主键关系。如图所示
-
在实体中的表达,例如员工与角色对象,分别在双方的实体中声明私有的对方set集合属性,在员工对象中创建private Set<角色> roles; 在角色表中创建private Set<员工> users; 这样两方都能使用集合来表达拥有多个对方。如图所示
-
在对象关系映射配置文件中表达
-
在员工关系映射配置文件中
<!-- 多对多关系表达 --> <!-- name属性:集合属性名 table:配置中间表名 key column:外键,别人引用我的外键列名 Class:我与那个类是多对多关系 column:外键,我引用别人的外键列名 --> <!-- cascade级联操作: save-update: 级联保存更新 delete: 级联删除 all:级联保存更新+级联删除 结论:cascade简化代码书写。该属性使不使用无所谓,建议要用只用save-update 如果使用delete操作太过危险。尤其是在多对多中,不建议使用。 --> <set name="roles" table="sys_user_role" cascade="save-update"> <key column="user_id"></key> <many-to-many class="Role" column="role_id"></many-to-many> </set>
-
在角色关系配置文件中
<!-- 使用inverse属性 true:放弃维护外键关系 false(默认值):维护关系 结论:将来在开发中,如果遇到多对多关系,一定要选择一方放弃维护关系。 一般谁来放弃要看业务方向。列如:录入员工时,需要为员工指定所属角色。 那么业务方向就是由员工维护角色。角色不需要维护与员工的关系。所以角色放弃维护。 --> <set name="users" table="sys_user_role" inverse="true"> <key column="role_id"></key> <many-to-many class="User" column="user_id"></many-to-many> </set>
-
-
多对多关系在实际中的应用
@Test //保存员工以及角色 public void fun1(){ //1、获得session Session session = HibernateUtils.openSession(); //2、开启事务 Transaction tx = session.beginTransaction(); //--------------------------------------------- //3.操作 //1.创建两个USER User u1 = new User(); u1.setUser_name("大明星"); User u2 = new User(); u2.setUser_name("清子"); //2。创建两Role Role r1 = new Role(); r1.setRole_name("保洁"); Role r2 = new Role(); r2.setRole_name("前台"); //3.用户表达关系 u1.getRoles().add(r1); u1.getRoles().add(r2); u2.getRoles().add(r1); u2.getRoles().add(r2); //4.角色表达 r1.getUsers().add(u1); r1.getUsers().add(u2); r2.getUsers().add(u1); r2.getUsers().add(u2); //5.调用save方法一次保存 session.save(u1); session.save(u2); session.save(r1); session.save(r2); //------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
@Test //为大明星写入一个角色 public void fun2(){ //1、获得session Session session = HibernateUtils.openSession(); //2、开启事务 Transaction tx = session.beginTransaction(); //--------------------------------------------- //3.操作 //1。获得大明星用户 User user = session.get(User.class, 1l); //2.创建公关角色 Role r = new Role(); r.setRole_name("公关"); //3.将角色添加到用户中 user.getRoles().add(r); //4.将角色转为持久化 session.save(r); //------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
@Test //为大明星解除一个角色 public void fun3(){ //1、获得session Session session = HibernateUtils.openSession(); //2、开启事务 Transaction tx = session.beginTransaction(); //--------------------------------------------- //3.操作 //1。获得大明星用户 User user = session.get(User.class, 1l); //2.获得要操作的角色对象 Role r1 = session.get(Role.class, 1l); Role r2 = session.get(Role.class, 2l); //3.将角色从用户的角色集合中移除 user.getRoles().remove(r1); user.getRoles().remove(r2); //------------------------------------------- //4.提交事务 tx.commit(); //5.关闭资源 session.close(); }
-
-