Hibernate5.x表与表之间的关系操作代码实现

Posted dielianhua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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集合里面把角色移除

 

以上是关于Hibernate5.x表与表之间的关系操作代码实现的主要内容,如果未能解决你的问题,请参考以下文章

Mysql 表与表之间的关系

07表与表之间的关系

多表查询

表与表之间关系回顾

表与表之间的关系

数据库表与表之间的关系