Hibernate5.x表与表之间的关系操作代码实现
一、一对多操作(客户和联系人)
1、一对多基本实现步骤
第一步 创建两个实体类,客户和联系人


第二步 让两个实体类之间互相表示
(1)在客户实体类里面表示多个联系人
- 一个客户里面有多个联系人

(2)在联系人实体类里面表示所属客户
- 一个联系人只能属于一个客户

第三步 配置映射关系
(1)一般一个实体类对应一个映射文件
(2)把映射最基本配置完成
(3)在映射文件中,配置一对多关系
- 在客户映射文件中,表示所有联系人
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <!-- hibernate入门 搭建hibernate环境 第一步 导入hibernate的jar包 --> 4 <!-- 映射配置文件dtd约束 --> 5 <!DOCTYPE hibernate-mapping PUBLIC 6 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 7 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 8 <hibernate-mapping> 9 <class name="com.cn.entity.Custom" table="t_custom"> 10 <id name="cid" column="cid"> 11 <generator class="native"></generator> 12 </id> 13 <property name="custName" column="custName"></property> 14 <property name="custLevel" column="custLevel"></property> 15 <property name="custSource" column="custSource"></property> 16 <property name="custPhone" column="custPhone"></property> 17 <property name="Mobile" column="Mobile"></property> 18 <!-- 在客户映射文件中,表示所有联系人,使用set标签表示所有联系人 19 set标签里面有name属性:属性值写在客户实体类里面表示联系人的set集合名称 --> 20 <!-- cascade属性:级联添加 级联删除 --> 21 <!-- batch-size:值越大发送语句越少 --> 22 <set name="setLinkMan" cascade="save-update,delete" batch-size="10"> 23 <!-- 一对多建表,有外键 24 hibernate机制:双向维护外键,在一和多那一方都配置外键 column属性值:外键名称 --> 25 <key column="clid"></key> 26 <!-- 客户所有联系人,class里面写联系人实体类全路径 --> 27 <one-to-many class="com.cn.entity.LinkMan"/> 28 </set> 29 </class> 30 </hibernate-mapping>
- 在联系人映射文件中,表示所属客户
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <!-- hibernate入门 搭建hibernate环境 第一步 导入hibernate的jar包 --> 4 <!-- 映射配置文件dtd约束 --> 5 <!-- 最好每一个实体类对应一个映射文件 --> 6 <!DOCTYPE hibernate-mapping PUBLIC 7 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 8 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 9 <hibernate-mapping> 10 <class name="com.cn.entity.LinkMan" table="t_linkMan"> 11 <id name="lkm_id" column="lkm_id"> 12 <generator class="native"></generator> 13 </id> 14 <property name="lkm_name" column="lkm_name"></property> 15 <property name="lkm_gender" column="lkm_gender"></property> 16 <property name="lkm_phone" column="lkm_phone"></property> 17 18 <!-- 表示联系人所属客户 name属性:因为在联系人实体类使用custom对象表示,写custom名称 19 class属性:custom全路径 column属性:外键名称 --> 20 <many-to-one name="custom" class="com.cn.entity.Custom" column="clid"></many-to-one> 21 </class> 22 </hibernate-mapping>
第四步 创建核心配置文件,把映射文件引入到核心配置文件中
![]()
2、一对多级联操作
1 级联保存:添加一个客户,为这个客户添加多个联系人
2 级联删除:删除某一个客户,这个客户里面的所有的联系人也删除
(1)添加客户,为这个客户添加一个联系人
① 复杂写法
//级联添加
@Test
public void testAdd1() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
sessionFactory = DUtils.getSessionFactory();
session = DUtils.getSessionObject();
//开启事务
tx = session.beginTransaction();
//创建客户和联系人对象
Custom custom = new Custom();
custom.setCustName("网易");
custom.setCustLevel("vip");
custom.setCustSource("网络传播");
custom.setCustPhone("220");
custom.setMobile("333");
LinkMan linkman = new LinkMan();
linkman.setLkm_name("mary");
linkman.setLkm_gender("女");
linkman.setLkm_phone("8888");
//2在客户表示所有联系人 在联系人表示客户
//建立客户对象和联系人对象关系
//2.1 把联系人对象放到客户对象的set集合里面
custom.getSetLinkMan().add(linkman);
//2.2 把客户对象放到联系人里面
linkman.setCustom(custom);
//3 保存到数据库
session.save(custom);
session.save(linkman);
//提交事务
tx.commit();
}catch(Exception e) {
e.printStackTrace();
//回滚事务
tx.rollback();
}
}
② 简化写法
- 一般根据客户添加联系人
第一步 在客户映射文件中进行配置
- 在客户映射文件里面set标签进行配置
![]()
第二步 创建客户和联系人对象,只需要把联系人放到客户里面就可以了,最终只需要保存客户就可以了

2、删除某个客户,把客户里面所有的联系人删除
第一步 在客户映射文件set标签,进行配置
(1)使用属性cascade属性值 delete
![]()
第二步 在代码中直接删除客户
(1)根据id查询对象,调用session里面delete方法删除

第三步 执行过程
(1)根据id查询客户

(2)根据外键id值查询联系人

(3)把联系人外键设置为null

(4)删除联系人和客户

3、一对多修改操作(inverse属性)

inverse属性
(1)因为hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改客户时候修改一次外键,修改联系人时候也修改一次外键,造成效率问题
(2)解决方式:让其中的一方不维护外键
- 一对多里面,让其中一方放弃外键维护
- 一个国家有总统,国家有很多人,总统不能认识国家所有人,国家所有人可以认识总统
(3)具体实现:在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性

二、多对多操作(用户和角色)
以用户和角色为例演示
第一步 创建实体类,用户和角色


第二步 让两个实体类之间互相表示
(1)一个用户里面表示所有角色,使用set集合

(2)一个角色有多个用户,使用set集合

第三步 配置映射关系
(1)基本配置
(2)配置多对多关系
- 在用户里面表示所有角色,使用set标签
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="com.cn.manytomany.User" table="t_user2"> 7 <id name="user_id" column="user_id"> 8 <generator class="native"></generator> 9 </id> 10 <property name="user_name" column="user_name"></property> 11 <property name="user_password" column="user_password"></property> 12 <!-- set标签:在用户里面表示所有角色 --> 13 <!-- 根据用户保存角色 --> 14 <set name="setRole" table="user_role" cascade="save-update"> 15 <key column="userid"></key> 16 <many-to-many class="com.cn.manytomany.Role" column="roleid"></many-to-many> 17 </set> 18 </class> 19 </hibernate-mapping>
- 在角色里面表示所有用户,使用set标签
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="com.cn.manytomany.Role" table="t_role2"> 7 <id name="role_id" column="role_id"> 8 <generator class="native"></generator> 9 </id> 10 <property name="role_name" column="role_name"></property> 11 <property name="role_memo" column="role_memo"></property> 12 <!-- set标签:在角色里面表示所有用户--> 13 <set name="setUser" table="user_role"> 14 <!-- key标签:角色在第三张表外键 --> 15 <key column="roleid"></key> 16 <many-to-many class="com.cn.manytomany.User" column="userid"></many-to-many> 17 </set> 18 </class> 19 </hibernate-mapping>
第四步 在核心配置文件中引入映射文件

第五步 测试代码
package com.cn.hibernate.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import com.cn.manytomany.Role;
import com.cn.manytomany.User;
import com.cn.utils.DUtils;
/**
* 测试多对多的关系
* @author 葛云霞
* 级联删除 级联保存
*/
public class TestManyToMany {
@Test
public void testSave() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
sessionFactory = DUtils.getSessionFactory();
session = sessionFactory.openSession();
tx = session.beginTransaction();
//演示级联保存
//演示多对多级联保存
//添加两个用户,为每一个用户添加两个角色
User user1 = new User();
user1.setUser_name("lucy");
user1.setUser_password("123");
User user2 = new User();
user2.setUser_name("mary");
user2.setUser_password("456");
Role role1 = new Role();
role1.setRole_name("总经理");
role1.setRole_memo("总经理");
Role role2 = new Role();
role2.setRole_name("保安");
role2.setRole_memo("保安");
Role role3 = new Role();
role3.setRole_name("员工");
role3.setRole_memo("员工");
//建立关系
//User--r1/r2
user1.getSetRole().add(role1);
user1.getSetRole().add(role2);
//User--r2/r3
user2.getSetRole().add(role2);
user2.getSetRole().add(role3);
//保存用户
session.save(user1);
session.save(user2);
tx.commit();
} catch(Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
}
第六步 维护第三张表的关系
1 用户和角色多对多关系,维护关系通过第三张表维护
2 让某个用户有某个角色
第一步 根据id查询用户和角色
第二步 把角色放到用户里面
(1)把角色对象放到用户set集合
3 让某个用户没有某个角色
第一步 根据id查询用户和角色

第二步 从用户里面把角色去掉
(1)从set集合里面把角色移除

浙公网安备 33010602011771号