Hibernate——一对多,多对多关系

一、一对多关系

表中的表达

实体中的表达

ORM元数据配置

1)一对多配置

2)多对一配置

操作关联属性

1、添加客户,添加联系方式

@Test
public void func1() {
    Session session = HibernateUtils.openSession();
    Transaction tx = session.beginTransaction();
    //----------------------------------------

    // 1.实例化客户实体
    Customer c = new Customer();
    c.setCust_name("鑫哥论文");
    
    // 2.实例化联系人
    LinkMan lm1 = new LinkMan();
    lm1.setLkm_name("xxx");

    LinkMan lm2 = new LinkMan();
    lm2.setLkm_name("jasonyu");

    // 3.获取客户对象中的集合,添加进去
    c.getLinkMens().add(lm1);
    c.getLinkMens().add(lm2);

    // 4.设置外键
    lm1.setCustomer(c);
    lm2.setCustomer(c);

    session.save(c);
    session.save(lm1);
    session.save(lm2);

    //----------------------------------------
    tx.commit();
    session.close();
}

2、只添加联系人

@Test
public void func2() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//----------------------------------------

// 1.获取要操作的客户对象
Customer customer = session.get(Customer.class, 1L);
// 2.实例化新联系人
LinkMan lk3 = new LinkMan();
lk3.setLkm_name("张宝岩");
// 3.为客户对象中的联系人集合中添加新的联系人
customer.getLinkMens().add(lk3);
// 4.将联系人中的custom属性设置为 客户对象
lk3.setCustomer(customer);
// 5.保存联系人对象(不用保存客户对象)
session.save(lk3);

//----------------------------------------
tx.commit();
session.close();
}

3、清除某个联系人的外键关联

@Test
public void func3() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//----------------------------------------

// 1.获取要操作的客户对象
Customer customer = session.get(Customer.class, 1L);
// 2.获取要操作的联系人
LinkMan lk = session.get(LinkMan.class, 2L);
// 3.将联系人从客户对象中的联系人集合移除
customer.getLinkMens().remove(lk);
// 4.将联系人的customer设置为null***
lk.setCustomer(null);

//----------------------------------------
tx.commit();
session.close();
}

4、直接删除联系人

@Test
public void func4() {
    Session session = HibernateUtils.openSession();
    Transaction tx = session.beginTransaction();
    //----------------------------------------

    // 1.获取要操作的客户对象
    Customer customer = session.get(Customer.class, 1L);
    // 2.获取要操作的联系人
    LinkMan lk = session.get(LinkMan.class, 2L);
    // 3.将联系人从客户对象中的联系人集合移除
    customer.getLinkMens().remove(lk);
    // 4.将联系人的customer设置为null***
    session.delete(lk);

    //----------------------------------------
    tx.commit();
    session.close();
}

级联操作

元数据配置文件

 <!-- 
	级联操作:	cascade
		save-update: 级联保存更新(只save一个表的实例,另一个关联表的实例也save)
		delete:级联删除(删除一个表的,另一个关联表的相应字段也被删除)
		all:save-update+delete
	级联操作: 简化操作.目的就是为了少些两行代码.
  -->

<set name="linkMens" cascade="save-update"  >
	<key column="lkm_cust_id" ></key>
	<one-to-many class="LinkMan" />
</set>

结论: 简化操作.一定要用save-update,不建议使用delete.

关系维护

在保存时.两方都会维护外键关系,关系维护两次,冗余了;多余的维护关系语句,显然是客户这一端在维护关系

<!-- inverse属性: 配置关系是否维护. 
		true: customer不维护关系
		false(默认值): customer维护关系
		
	inverse属性: 性能优化,提高关系维护的性能.
	原则: 无论怎么放弃,总有一方必须要维护关系.
	一对多关系中: 一的一方放弃,也只能一的一方放弃,多的一方不能放弃.
  -->
<set name="linkMens" inverse="true">
	<key column="lkm_cust_id" ></key>
	<one-to-many class="LinkMan" />
</set>

二、多对多关系

表中关系表达

实体中表达

元数据配置

普通操作

1、添加职位和职员

@Test
public void func1(){

    Session session = HibernateUtils.openSession();

    Transaction tx = session.beginTransaction();

    // ----------------------------------------

    // 1.获取两个Role 职位对象
    Role r1 = new Role();
    r1.setRole_name("保洁");
    Role r2 = new Role();
    r2.setRole_name("保安");

    // 2.获取两个User 职员对象
    User u1 = new User();
    u1.setUser_name("计震宇");
    User u2 = new User();
    u2.setUser_name("张宝岩");

    // 3.将2个用户送进两个职位下的用户列表中
    r1.getUsers().add(u1);
    r1.getUsers().add(u2);

    r2.getUsers().add(u1);
    r2.getUsers().add(u2);

    // 4.将两个职位送入2个用户下的职位列表中
    u1.getRoles().add(r1);
    u1.getRoles().add(r2);

    u2.getRoles().add(r1);
    u2.getRoles().add(r2);

    // 5.保存
    session.save(u1);
    session.save(u2);
    session.save(r1);
    session.save(r2);

    // ----------------------------------------

    tx.commit();
    session.close();
}

 这种平常不过的操作,会报错,因为双方都维护第三张表,这样就维护了两次,所以我们要使用inverse属性,让一方放弃维护

2、为计震宇添加一个职位

@Test
public void func1(){

    Session session = HibernateUtils.openSession();

    Transaction tx = session.beginTransaction();

    // ----------------------------------------

    // 1.获取新Role 职位对象
    Role role = new Role();
    role.setRole_name("男公关");
    // 2.获取计震宇角色
    User user = session.get(User.class, 1L);
    // 3.将计震宇放进新职位
    user.getRoles().add(role);
    // 4.将新职位放进计震宇
    role.getUsers().add(user);
    // 5.保存(如果开启了级联操作,这句可以省略)
    session.save(role);

    // ----------------------------------------

    tx.commit();
    session.close();
}

3、为计震宇解除一个角色

@Test
public void func1(){

    Session session = HibernateUtils.openSession();

    Transaction tx = session.beginTransaction();

    // ----------------------------------------

    // 1.获取要解除的Role 职位对象
    Role role = session.get(Role.class, 2L);
    // 2.获取计震宇角色
    User user = session.get(User.class, 1L);
    // 3.将职位从列表找中移除
    user.getRoles().remove(role);
    // 4.将计震宇从职位下的员工列表中移除(开启级联可以省略这句)
    role.getUsers().remove(user);

    // ----------------------------------------

    tx.commit();
    session.close();
}

级联操作

原文地址:https://www.cnblogs.com/x54256/p/8467698.html