系列文章目录
Hibernate框架【三】——基本映射——一对一映射
Hibernate框架【四】——基本映射——多对一和一对多映射
基本映射——多对多映射
- 系列文章目录
- 前言
- 一、多对多映射是什么?
- 二、hibernate多对多关联映射(单向)
- 1.实体结构
- 2.示意图
- 3.对应的实体xml配置文件
- 4.生成的表结构
- 5.核心代码
- 1.插入数据
- 2.查询数据
- 三、hibernate多对多关联映射(双向)
- 1.实体结构
- 2.对应实体的xml配置文件
- 3.生成的表结构
- 4.核心代码
- 1.插入数据
- 2.查询数据(先查User)
- 3.查询数据(先查Role)
- 四、总结
前言
由于公司项目上进行面向对象的架构设计对于ORM部分使用的是Spring Data JPA框架。将ORM完全交给Spring Data JPA框架,而Hibernate是Spring Data JPA的实现方式之一,通过对HIbernate框架的学习能够更好的理解ORM框架,以及Spring Data JPA框架。
下面的博客是对于Hibernate框架中的基本映射中的一对一映射进行的实践,总结的并不全面,旨在对于一对一映射关系有一个宏观了解并能够进行基本运用。
一、多对多映射是什么?
在Hibernate中,多对多映射表示多个实体之间的多对多关系,其中一个实体可以与多个另一实体相关联,并且每个另一实体也可以与多个该实体相关联。
在多对多映射中,需要创建一个中间表(关联表)来存储实体之间的关联关系。该中间表通常包含两个外键列,分别指向参与关联的两个实体的主键。
当然多对多映射关系,也分为单向关联和双向关联。
二、hibernate多对多关联映射(单向)
案例:现在有两个实体User实体和Role,分别表现出多对多的关系,一个用户可以有多个角色,一个角色可以包含多个用户。
1.实体结构
package com.wangwei.hibernate;
import java.util.Set;
public class User {
private int id;
private String name;
private Set roles;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
}
package com.wangwei.hibernate;
public class Role {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.示意图
3.对应的实体xml配置文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.wangwei.hibernate.Role" table="t_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.wangwei.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="user_id"/>
<many-to-many class="com.wangwei.hibernate.Role" column="role_id" />
</set>
</class>
</hibernate-mapping>
4.生成的表结构
5.核心代码
1.插入数据
public class Many2ManyTest extends TestCase {
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Role r1 = new Role();
r1.setName("数据录入人员");
session.save(r1);
Role r2 = new Role();
r2.setName("商务主管");
session.save(r2);
Role r3 = new Role();
r3.setName("商务经理");
session.save(r3);
Role r4 = new Role();
r4.setName("项目会计");
session.save(r4);
User u1 = new User();
u1.setName("张三");
Set u1Roles = new HashSet();
u1Roles.add(r1);
u1Roles.add(r2);
u1.setRoles(u1Roles);
session.save(u1);
User u2 = new User();
u2.setName("李四");
Set u2Roles = new HashSet();
u2Roles.add(r1);
u2Roles.add(r2);
u2Roles.add(r3);
u2.setRoles(u2Roles);
session.save(u2);
User u3 = new User();
u3.setName("王五");
Set u3Roles = new HashSet();
u3Roles.add(r3);
u3Roles.add(r4);
u3.setRoles(u3Roles);
session.save(u3);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
发出的SQL语句
数据库中的数据
2.查询数据
public void testLoad1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
User user = (User)session.load(User.class, 2);
System.out.println(user.getName());
for (Iterator iter=user.getRoles().iterator(); iter.hasNext();) {
Role role = (Role)iter.next();
System.out.println(role.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
发出的sql语句和打印的结果
三、hibernate多对多关联映射(双向)
1.实体结构
package com.wangwei.hibernate;
import java.util.Set;
public class Role {
private int id;
private String name;
private Set User;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getUser() {
return User;
}
public void setUser(Set user) {
User = user;
}
}
package com.wangwei.hibernate;
import java.util.Set;
public class User {
private int id;
private String name;
private Set roles;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
}
2.对应实体的xml配置文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.wangwei.hibernate.Role" table="t_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="user" table="t_user_role">
<key column="role_id" not-null="true"/>
<many-to-many class="com.wangwei.hibernate.User" column="user_id"/>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.wangwei.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="user_id"/>
<many-to-many class="com.wangwei.hibernate.Role" column="role_id" />
</set>
</class>
</hibernate-mapping>
注意事项:
- 生成的中间表名称必须一样
- 生成的中间表中的字段必须一样
3.生成的表结构
4.核心代码
1.插入数据
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Role r1 = new Role();
r1.setName("数据录入人员");
session.save(r1);
Role r2 = new Role();
r2.setName("商务主管");
session.save(r2);
Role r3 = new Role();
r3.setName("商务经理");
session.save(r3);
Role r4 = new Role();
r4.setName("项目会计");
session.save(r4);
User u1 = new User();
u1.setName("张三");
Set u1Roles = new HashSet();
u1Roles.add(r1);
u1Roles.add(r2);
u1.setRoles(u1Roles);
session.save(u1);
User u2 = new User();
u2.setName("李四");
Set u2Roles = new HashSet();
u2Roles.add(r1);
u2Roles.add(r2);
u2Roles.add(r3);
u2.setRoles(u2Roles);
session.save(u2);
User u3 = new User();
u3.setName("王五");
Set u3Roles = new HashSet();
u3Roles.add(r3);
u3Roles.add(r4);
u3.setRoles(u3Roles);
session.save(u3);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
生成的sql语句
表中的数据
2.查询数据(先查User)
public void testLoad1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
User user = (User)session.load(User.class, 2);
System.out.println(user.getName());
for (Iterator iter=user.getRoles().iterator(); iter.hasNext();) {
Role role = (Role)iter.next();
System.out.println(role.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
发出的sql语句和打印的结果
3.查询数据(先查Role)
public void testLoad2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Role role = (Role)session.load(Role.class, 1);
System.out.println(role.getName());
for (Iterator iter=role.getUser().iterator(); iter.hasNext();) {
User user = (User)iter.next();
System.out.println(user.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
发出的sql语句和结果
四、总结
如何选择多对多的单向关联还是多项关联。主要取决于实际的业务需要。
1.如果只需要从一个实体导航到另一个实体,而无需反向导航,那么使用单向关联更为合适。
2.如果不需要再两个实体上进行关系的维护,添加、删除、更新等,那么单向关联更合适。
3.维护上:单向关联不会引入额外的的关系