016 多对多关联映射 单向(many-to-many)
- 一般的设计中,多对多关联映射,需要一个中间表
- Hibernate会自动生成中间表
- Hibernate使用many-to-many标签来表示多对多的关联
- 多对多的关联映射,在实体类中,跟一对多一样,也是用集合来表示的。
实例场景:
用户与他的角色(一个用户拥有多个角色,一个角色还可以属于多个用户)

Role实体类:
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;
}
}
User实体类:
public class User {
private int id;
private String name;
private Set roles;//Role对象的集合
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;
}
}
Role映射文件:
<hibernate-mapping>
<class name="com.wjt276.hibernate.Role" table="t_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
</class>
</hibernate-mapping>
User映射文件:
<hibernate-mapping>
<class name="com.wjt276.hibernate.User" table="t_user">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<!--使用<set>标签映射集合(set),标签中的name值为对象属性名(集合roles),而使用table属性是用于生成第三方表名称,例:table="t_user_role",但是第三方面中的字段是自动加入的,作为外键分别指向其它表。
所以表<key>标签设置,例:<key column="userid"/>,意思是:在第三方表(t_user_role)中加入一个外键并且指向当前的映射实体类所对应的表(t_user).使用<many-to-many>来指定此映射集合所对象的类(实例类),并且使用column属性加入一个外键指向Role实体类所对应的表(t_role) -->
<set name="roles" table="t_user_role">
<key column="userid"/>
<many-to-many class="com.wjt276.hibernate.Role" column="roleid"/>
</set>
</class>
</hibernate-mapping>
导出至数据库表所生成SQL语句
|
create table t_role (id integer not null auto_increment, name varchar(255), primary key (id)) create table t_user (id integer not null auto_increment, name varchar(255), primary key (id)) create table t_user_role (userid integer not null, roleid integer not null, primary key (userid, roleid)) alter table t_user_role add index FK331DEE5F1FB4B2D4 (roleid), add constraint FK331DEE5F1FB4B2D4 foreign key (roleid) references t_role (id) alter table t_user_role add index FK331DEE5F250A083E (userid), add constraint FK331DEE5F250A083E foreign key (userid) references t_user (id) |
注:根据DDL语句可以看出第三方表的主键是一个复合主键(primary key (userid, roleid)),也就是说记录不可以有相同的数据。
数据库表及结构:

多对多关联映射 单向数据存储:
session = HibernateUtils.getSession();
tx = 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);
User u1 = new User();
u1.setName("10");
Set<Role> u1Roles = new HashSet<Role>();
u1Roles.add(r1);
u1Roles.add(r2);
u1.setRoles(u1Roles);
User u2 = new User();
u2.setName("祖儿");
Set<Role> u2Roles = new HashSet<Role>();
u2Roles.add(r2);
u2Roles.add(r3);
u2.setRoles(u2Roles);
User u3 = new User();
u3.setName("成龙");
Set<Role> u3Roles = new HashSet<Role>();
u3Roles.add(r1);
u3Roles.add(r2);
u3Roles.add(r3);
u3.setRoles(u3Roles);
session.save(u1);
session.save(u2);
session.save(u3);
tx.commit();
发出SQL语句:
|
Hibernate: insert into t_role (name) values (?) Hibernate: insert into t_role (name) values (?) Hibernate: insert into t_role (name) values (?) Hibernate: insert into t_user (name) values (?) Hibernate: insert into t_user (name) values (?) Hibernate: insert into t_user (name) values (?) Hibernate: insert into t_user_role (userid, roleid) values (?, ?) Hibernate: insert into t_user_role (userid, roleid) values (?, ?) Hibernate: insert into t_user_role (userid, roleid) values (?, ?) Hibernate: insert into t_user_role (userid, roleid) values (?, ?) Hibernate: insert into t_user_role (userid, roleid) values (?, ?) Hibernate: insert into t_user_role (userid, roleid) values (?, ?) Hibernate: insert into t_user_role (userid, roleid) values (?, ?) |
注:前三条SQL语句,添加Role记录,第三条到第六条添加User,最后7条SQL语句是在向第三方表(t_user_role)中添加多对多关系(User与Role关系)
多对多关联映射 单向数据加载:
session = HibernateUtils.getSession();
tx = session.beginTransaction();
User user = (User)session.load(User.class, 1);
System.out.println("user.name=" + user.getName());
for (Iterator<Role> iter = user.getRoles().iterator(); iter.hasNext();){
Role role = (Role) iter.next();
System.out.println(role.getName());
}
//提交事务
tx.commit();
|
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=? user.name=10 Hibernate: select roles0_.userid as userid1_, roles0_.roleid as roleid1_, role1_.id as id2_0_, role1_.name as name2_0_ from t_user_role roles0_ left outer join t_role role1_ on roles0_.roleid=role1_.id where roles0_.userid=? 商务主管 数据录入人员 |
016 多对多关联映射 单向(many-to-many)的更多相关文章
- java之hibernate之单向的多对多关联映射
这篇 单向的多对多关联映射 1.如何在权限管理中,角色和权限之间的关系就是多对多的关系,表结构为: 2.类结构 Permission.java public class Permission impl ...
- (Hibernate进阶)Hibernate映射——多对多关联映射(八)
多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数 ...
- Hibernate(六)——多对多关联映射
前面几篇文章已经较讲解了三大种关联映射,多对多映射就非常简单了,不过出于对关联映射完整性的考虑,本文还是会简要介绍下多对多关联映射. 1.单向多对多关联映射 情景:一个用户可以有多个角色,比如数据录入 ...
- 017 多对多关联映射 双向(many-to-many)
多对多关联映射 双向 两方都持有对象引用,修改对象模型,但数据的存储没有变化. 再修改映射文件: public class Role { private int id; private String ...
- 014 一对多关联映射 单向(one-to-many)
在对象模型中,一对多的关联关系,使用集合来表示. 实例场景:班级对学生:Classes(班级)和Student(学生)之间是一对多的关系. 多对一.一对多的区别: 多对一关联映射:在多的端加入一个外键 ...
- 一口一口吃掉Hibernate(六)——多对多关联映射
今天来说说hibernate中的多对多关联映射,多对多关联映射涉及到单向映射和双向映射2种. 首先举个多对多关联例子:用户User和角色Role,一个用户可以属于多个角色,一个角色可以有多个用户.这就 ...
- 【SSH系列】Hibernate映射 -- 多对多关联映射
映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论 ...
- 【SSH进阶之路】Hibernate映射——多对多关联映射(八)
上篇博文[SSH进阶之路]Hibernate映射——一对多关联映射(七),我们介绍了一对多关联映射,它是多对多关联映射的基础. 多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接 ...
- Hibernate的关联映射——单向1-N关联
Hibernate的关联映射--单向1-N关联 单向1-N关联的持久化类里需要使用集合属性.因为1的一端需要访问N的一端,而N的一端将以集合(Set)形式表现.从这个意义上来看,1-N(实际上还包括N ...
随机推荐
- scrollWidth,offsetWidth,clientWidth,width;scrollHeight,offsetHeight,clientHeight,height;offsetTop,scrollTop,top;offsetLeft,scrollLeft,left还有谁
题中的那么多属性让人头都大了,他们到底是什么意思?不同浏览器的实现是一样的吗?以下所有结论来自chrome版本 53.0.2785.89 (64-bit)和firefox版本52.0.2,操作系统ub ...
- WPF集合控件实现分隔符(ItemsControl Splitter)
在WPF的集合控件中常常需要在每一个集合项之间插入一个分隔符样式,但是WPF的ItemsControl没有相关功能的直接实现,所以只能考虑曲线救国,经过研究,大概想到了以下两种实现方式. 先写出Ite ...
- BS结构中,web如何将数据进行DES加密并写道IC卡中
在IC卡应用系统中,一般都要对IC卡数据进行DES加密,以保证数据的安全.友我科技RFID读写器云服务2.0充分考虑了这个需求,只需要软件工程师简单的配置即可实现数据的加解密并且写到数据块中.如下图所 ...
- python_Tornado_web_框架_分页
如何实现web_框架_分页? -- 思考什么是xss跨站攻击? --别人把js代码提交到后台,然后从后台返回数据的时候,别人上传的js变成html中的代码, 就会插入别人的代码,带来极大的信息泄露的风 ...
- windows下nginx的安装及使用方法入门
nginx功能之一可以启动一个本地服务器,通过配置server_name和root目录等来访问目标文件 一. 下载 http://nginx.org/ 下载后解压 二. 修改配置文件 ngin ...
- js继承之原型链方式实现
温故而知新: 在之前的文章已经重点了解了原型对象,今天就理一理这个原型对象在原型链式的继承中的使用 function a(x,y){this.x=x;this.y=y;} //定义一个函数,当构造函数 ...
- Objective-C 实用关键字详解1「面试、工作」看我就 🐒 了 ^_^.
在写项目 或 阅读别人的代码(一些优秀的源码)中,总能发现一些常见的关键字,随着编程经验的积累大部分还是知道是什么意思 的. 相信很多开发者跟我当初一样,只是基本的常用关键字定义属性会使用,但在关键字 ...
- SELECT中(非常)常用的子查询操作
MySQL中的子查询 是在MySQL中经常使用到的一个操作,不仅仅是用在DQL语句中,在DDL语句.DML语句中也都会常用到子查询. 子查询的定义: 子查询是将一个查询语句嵌套在另一个查询语句中: 在 ...
- spring学习总结一----控制反转与依赖注入
spring作为java EE中使用最为广泛的框架,它的设计体现了很多设计模式中经典的原则和思想,所以,该框架的各种实现方法非常值得我们去研究,下面先对spring中最为重要的思想之一----控制反转 ...
- StringHelper--封转自己的字符串工具类
我们每次开发项目,都会有很多的关于字符串的处理,字符串的处理太常见了,无法避免,那么这时如果可以把常用的字符串处理封装成类,在以后的开发中应该会减少一些工作量,下面代码对一些常用的字符串处理进行了封装 ...