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集合里面把角色移除