在我们实际项目中,多对多的情况也时长存在,比如最常见的就是系统管理的五张表,如下面的一个结构:

在本文学习hibernate多对多关联映射的实验中我简单的写几个字段,达到学习目的即可。

1.多对多的关系表达

1.关系型数据库(RDB)中的表达:

2.Java实体中的表达

3.orm配置文件中的表达:(注意每次添加了ORM映射文件都要加到主配置文件中)

User.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 配置表与实体对象的关系 -->
<!-- package属性:填写一个包名.在元素内部凡是需要书写完整类名的属性,可以直接写简答类名了. -->
<hibernate-mapping package="cn.qlq.domain" >
<!--
class元素: 配置实体与表的对应关系的
name: 完整类名
table:数据库表名
-->
<class name="User" table="sys_user" >
<!-- id元素:配置主键映射的属性
name: 填写主键对应属性名
column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
每个类型有三种填法: java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
-->
<id name="user_id" >
<!-- generator:主键生成策略 -->
<!--identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键. -->
<generator class="native"></generator>
</id>
<!-- property元素:除id之外的普通属性映射
name: 填写属性名
column(可选): 填写列名
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
每个类型有三种填法: java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
-->
<property name="User_name" length="20"/>
<property name="user_state"/> <!-- 集合,多对多关系,在配置文件中配置 -->
<!--
name:集合属性名字
table:中间表名
-->
<set name="roles" table="sys_user_role">
<!-- column:外键,别人引用我的外键列名 -->
<key column="user_id" ></key>
<!-- class:我与哪个表是多对多关系,column:外键,我引用别人的外键 -->
<many-to-many class="Role" column="role_id"></many-to-many>
</set>
</class>
</hibernate-mapping>

Role.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 配置表与实体对象的关系 -->
<!-- package属性:填写一个包名.在元素内部凡是需要书写完整类名的属性,可以直接写简答类名了. -->
<hibernate-mapping package="cn.qlq.domain" >
<!--
class元素: 配置实体与表的对应关系的
name: 完整类名
table:数据库表名
-->
<class name="Role" table="sys_role" >
<!-- id元素:配置主键映射的属性
name: 填写主键对应属性名
column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
每个类型有三种填法: java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
-->
<id name="role_id" >
<!-- generator:主键生成策略 -->
<!--identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键. -->
<generator class="native"></generator>
</id>
<!-- property元素:除id之外的普通属性映射
name: 填写属性名
column(可选): 填写列名
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
每个类型有三种填法: java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
-->
<property name="role_name" length="20"/>
<property name="role_state"/> <!-- 集合,多对多关系,在配置文件中配置 -->
<!--
name:集合属性名字
table:中间表名
-->
<set name="users" table="sys_user_role">
<!-- column:外键,别人引用我的外键列名 -->
<key column="role_id" ></key>
<!-- class:我与哪个表是多对多关系,column:外键,我引用别人的外键 -->
<many-to-many class="User" column="user_id"></many-to-many>
</set>
</class>
</hibernate-mapping>

4.测试建表结果:

    随便执行一个hibernate测试,会加载主配置文件并进行建表。

mysql> desc sys_user;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| user_id | bigint(20) | NO | PRI | NULL | auto_increment |
| User_name | varchar(20) | YES | | NULL | |
| user_state | char(1) | YES | | NULL | |
+------------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec) mysql> desc sys_role;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| role_id | bigint(20) | NO | PRI | NULL | auto_increment |
| role_name | varchar(20) | YES | | NULL | |
| role_state | varchar(255) | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec) mysql> desc sys_user_role;
+---------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| user_id | bigint(20) | NO | PRI | NULL | |
| role_id | bigint(20) | NO | PRI | NULL | |
+---------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

5.修改ORM配置中set元素配置对set元素的进一步解释

User.hbm.xml

Role.hbm.xml

 修改之后查看建表语句:

mysql> show create table sys_user_role\G
*************************** 1. row ***************************
Table: sys_user_role
Create Table: CREATE TABLE `sys_user_role` (
`user_id1` bigint(20) NOT NULL,
`role_id1` bigint(20) NOT NULL,
PRIMARY KEY (`role_id1`,`user_id1`),
KEY `FKgxeccay1ha1igqs2myct720lt` (`user_id1`),
CONSTRAINT `FKgxeccay1ha1igqs2myct720lt` FOREIGN KEY (`user_id1`) REFERENCES `sys_user` (`user_id`)
CONSTRAINT `FKtfvi95hnfedqqxi3rk1qmrwy7` FOREIGN KEY (`role_id1`) REFERENCES `sys_role` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

总结:

        <set name="users" table="sys_user_role">
<!-- column:外键,别人引用我的外键列名 (可以简单的理解为中间表的列名)-->
<key column="role_id1" ></key>
<!-- class:我与哪个表是多对多关系,column:外键,我引用别人的外键 -->
<many-to-many class="User" column="user_id1"></many-to-many>
</set>

  个人认为set元素更像是配置我与中间表的关系,key元素可以理解为中间表指向我的外键的名字,

    many-to-many中的class指的是与我是多对多的对象类名,column是在中间表中其对应的外键名字。

2.多对多操作

--------------------------第一次测试-----------------

1.测试保存:

    /**
*测试保存(多对多)
*/
@Test
public void fun1() {
//1.获取session
Session session = HibernateUtil.openSession();
//2.开启事务
Transaction tx = session.beginTransaction();
//3.构造数据(张三-总监、经理,李四---总监)
User u1 = new User();
u1.setUser_name("张三");
User u2 = new User();
u2.setUser_name("李四"); Role r1 = new Role();
r1.setRole_name("总监");
Role r2 = new Role();
r2.setRole_name("经理"); u1.getRoles().add(r1);
u1.getRoles().add(r2);
u2.getRoles().add(r1);
r1.getUsers().add(u1);
r1.getUsers().add(u2);
r2.getUsers().add(u1); session.save(u1);
session.save(u2);
session.save(r1);
session.save(r1);
//4.提交数据
tx.commit();
//5.关闭session
session.close();
}

执行会报错,因为两个表都维护关系,所以会像中间表插入两次记录,导致插入重复。如下错误:

解决办法:

  •   第一钟:将一方维护关系的代码注释掉:(一般开发中多对多的关系中都有一方放弃维护关系)

      

  • 第二种:配置文件中,设置一方放弃维护关系,例如:设置user放弃维护关系(一般开发中多对多的关系中都有一方放弃维护关系)

    

2.测试修改:

    /**
*新增一个角色,并给张三新增加一个角色
*/
@Test
public void fun2() {
//1.获取session
Session session = HibernateUtil.openSession();
//2.开启事务
Transaction tx = session.beginTransaction();
//3.构造数据(张三-总监、经理,李四---总监)
User u1 = session.get(User.class, 1l);
Role r3 = new Role();
r3.setRole_name("太监"); session.save(r3);//保存新角色 u1.getRoles().add(r3);//u1处于持久态,因此不用执行更新语句也可以更新 //4.提交数据
tx.commit();
//5.关闭session
session.close();
}

3.测试给张三删除一个角色

    /**
*为张三删除一个太监角色
*/
@Test
public void fun3() {
//1.获取session
Session session = HibernateUtil.openSession();
//2.开启事务
Transaction tx = session.beginTransaction();
//3.构造数据(张三-总监、经理,李四---总监)
User u1 = session.get(User.class, 1l);
Role r1 = session.get(Role.class, 3l); u1.getRoles().remove(r1);//u1处于持久态,因此不用执行更新语句也可以更新 //4.提交数据
tx.commit();
//5.关闭session
session.close();
}

查看发出的SQL:

Hibernate:
select
user0_.user_id as user_id1_3_0_,
user0_.User_name as User_nam2_3_0_,
user0_.user_state as user_sta3_3_0_
from
sys_user user0_
where
user0_.user_id=?
Hibernate:
select
role0_.role_id as role_id1_2_0_,
role0_.role_name as role_nam2_2_0_,
role0_.role_state as role_sta3_2_0_
from
sys_role role0_
where
role0_.role_id=?
Hibernate:
select
roles0_.user_id as user_id1_4_0_,
roles0_.role_id as role_id2_4_0_,
role1_.role_id as role_id1_2_1_,
role1_.role_name as role_nam2_2_1_,
role1_.role_state as role_sta3_2_1_
from
sys_user_role roles0_
inner join
sys_role role1_
on roles0_.role_id=role1_.role_id
where
roles0_.user_id=?
Hibernate:
delete
from
sys_user_role
where
user_id=?
and role_id=?

---------------------------第二次测试------------------

1.添加一个张三用户,并给其添加两个角色:经理和总监

    /**
* 测试1:添加一个张三用户
* 添加两个角色:经理、总监
*/
@Test
public void test1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction(); /******S 开始业务逻辑*************/
User u1 = new User();
u1.setUser_name("张三"); Role r1 = new Role();
Role r2 = new Role();
r1.setRole_name("总监");
r2.setRole_name("经理"); u1.getRoles().add(r1);
u1.getRoles().add(r2); session.save(u1);
session.save(r1);
session.save(r2);
/******E 开始业务逻辑*************/ tx.commit(); }

SQL:

Hibernate:
insert
into
sys_user
(user_name, user_state)
values
(?, ?)
Hibernate:
insert
into
sys_role
(role_name, role_state)
values
(?, ?)
Hibernate:
insert
into
sys_role
(role_name, role_state)
values
(?, ?)
Hibernate:
insert
into
sys_user_role
(user_id, role_id)
values
(?, ?)
Hibernate:
insert
into
sys_user_role
(user_id, role_id)
values
(?, ?)

结果:

mysql> select * from sys_user;
+---------+-----------+------------+
| user_id | user_name | user_state |
+---------+-----------+------------+
| 1 | 张三 | NULL |
+---------+-----------+------------+
1 row in set (0.03 sec) mysql> select * from sys_role;
+---------+-----------+------------+
| role_id | role_name | role_state |
+---------+-----------+------------+
| 1 | 总监 | NULL |
| 2 | 经理 | NULL |
+---------+-----------+------------+
2 rows in set (0.00 sec) mysql> select * from sys_user_role;
+---------+---------+
| user_id | role_id |
+---------+---------+
| 1 | 1 |
| 1 | 2 |
+---------+---------+
2 rows in set (0.00 sec)

2.给上面的张三解除与总监角色的关联关系

    /**
* 测试2:给上面的张三解除与总监角色的关联关系
*/
@Test
public void test2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction(); /******S 开始业务逻辑*************/
//get方法获取的对象都是持久态
User user = session.get(User.class,1l );
Role role = session.get(Role.class, 1l);
user.getRoles().remove(role);
/******E 开始业务逻辑*************/ tx.commit();
}

SQL:

Hibernate:
select
user0_.user_id as user_id1_3_0_,
user0_.user_name as user_nam2_3_0_,
user0_.user_state as user_sta3_3_0_
from
sys_user user0_
where
user0_.user_id=?
Hibernate:
select
role0_.role_id as role_id1_2_0_,
role0_.role_name as role_nam2_2_0_,
role0_.role_state as role_sta3_2_0_
from
sys_role role0_
where
role0_.role_id=?
Hibernate:
select
roles0_.user_id as user_id1_4_0_,
roles0_.role_id as role_id2_4_0_,
role1_.role_id as role_id1_2_1_,
role1_.role_name as role_nam2_2_1_,
role1_.role_state as role_sta3_2_1_
from
sys_user_role roles0_
inner join
sys_role role1_
on roles0_.role_id=role1_.role_id
where
roles0_.user_id=?
Hibernate:
delete
from
sys_user_role
where
user_id=?
and role_id=?

结果:

mysql> select * from sys_user;
+---------+-----------+------------+
| user_id | user_name | user_state |
+---------+-----------+------------+
| 1 | 张三 | NULL |
+---------+-----------+------------+
1 row in set (0.00 sec) mysql> select * from sys_role;
+---------+-----------+------------+
| role_id | role_name | role_state |
+---------+-----------+------------+
| 1 | 总监 | NULL |
| 2 | 经理 | NULL |
+---------+-----------+------------+
2 rows in set (0.00 sec) mysql> select * from sys_user_role;
+---------+---------+
| user_id | role_id |
+---------+---------+
| 1 | 2 |
+---------+---------+
1 row in set (0.00 sec)

3.删除经理角色,同时删除与张三的绑定关系

    /**
* 测试3:删除经理角色,同时删除与张三的绑定关系
*/
@Test
public void test3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction(); /******S 开始业务逻辑*************/
//get方法获取的对象都是持久态
User user = session.get(User.class,1l );
Role role = session.get(Role.class, 2l);
session.delete(role);
/******E 开始业务逻辑*************/ tx.commit();
}

SQL:

Hibernate:
select
user0_.user_id as user_id1_3_0_,
user0_.user_name as user_nam2_3_0_,
user0_.user_state as user_sta3_3_0_
from
sys_user user0_
where
user0_.user_id=?
Hibernate:
select
role0_.role_id as role_id1_2_0_,
role0_.role_name as role_nam2_2_0_,
role0_.role_state as role_sta3_2_0_
from
sys_role role0_
where
role0_.role_id=?
Hibernate:
delete
from
sys_user_role
where
role_id=?
Hibernate:
delete
from
sys_role
where
role_id=?

结果:

mysql> select * from sys_role;
+---------+-----------+------------+
| role_id | role_name | role_state |
+---------+-----------+------------+
| 1 | 总监 | NULL |
+---------+-----------+------------+
1 row in set (0.00 sec) mysql> select * from sys_user_role;
Empty set (0.00 sec)

4.新增一个秘书角色,并赋给张三该角色

    /**
* 测试4:新增一个秘书角色,并赋给张三该角色
*/
@Test
public void test4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction(); /******S 开始业务逻辑*************/
//get方法获取的对象都是持久态
Role r1 = new Role();
r1.setRole_name("秘书");
User user = session.get(User.class,1l);
user.getRoles().add(r1); session.save(r1);
session.update(user);
/******E 开始业务逻辑*************/ tx.commit();
}

SQL:

Hibernate:
select
user0_.user_id as user_id1_3_0_,
user0_.user_name as user_nam2_3_0_,
user0_.user_state as user_sta3_3_0_
from
sys_user user0_
where
user0_.user_id=?
Hibernate:
select
roles0_.user_id as user_id1_4_0_,
roles0_.role_id as role_id2_4_0_,
role1_.role_id as role_id1_2_1_,
role1_.role_name as role_nam2_2_1_,
role1_.role_state as role_sta3_2_1_
from
sys_user_role roles0_
inner join
sys_role role1_
on roles0_.role_id=role1_.role_id
where
roles0_.user_id=?
Hibernate:
insert
into
sys_role
(role_name, role_state)
values
(?, ?)
Hibernate:
insert
into
sys_user_role
(user_id, role_id)
values
(?, ?)

结果:

mysql> select * from sys_role;
+---------+-----------+------------+
| role_id | role_name | role_state |
+---------+-----------+------------+
| 1 | 总监 | NULL |
| 3 | 秘书 | NULL |
+---------+-----------+------------+
2 rows in set (0.00 sec) mysql> select * from sys_user_role;
+---------+---------+
| user_id | role_id |
+---------+---------+
| 1 | 3 |
+---------+---------+
1 row in set (0.00 sec)

5.修改秘书角色为总监秘书(不影响与用户的关联)

    /**
* 测试5:修改秘书角色为总监秘书(不影响与用户的关联)
*/
@Test
public void test5(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction(); /******S 开始业务逻辑*************/
//get方法获取的对象都是持久态
Role role = session.get(Role.class,3l);
role.setRole_name("总监秘书");
session.update(role);
/******E 开始业务逻辑*************/ tx.commit();
}

SQL:

Hibernate:
select
role0_.role_id as role_id1_2_0_,
role0_.role_name as role_nam2_2_0_,
role0_.role_state as role_sta3_2_0_
from
sys_role role0_
where
role0_.role_id=?
Hibernate:
update
sys_role
set
role_name=?,
role_state=?
where
role_id=?

结果:

mysql> select * from sys_user_role;
+---------+---------+
| user_id | role_id |
+---------+---------+
| 1 | 3 |
+---------+---------+
1 row in set (0.00 sec) mysql> select * from sys_role;
+---------+-----------+------------+
| role_id | role_name | role_state |
+---------+-----------+------------+
| 1 | 总监 | NULL |
| 3 | 总监秘书 | NULL |
+---------+-----------+------------+
2 rows in set (0.00 sec)

6.删除一个用户,会自动删除中间表

mysql> select * from sys_user_role;
+---------+---------+
| user_id | role_id |
+---------+---------+
| 1 | 3 |
+---------+---------+
1 row in set (0.00 sec) mysql> select * from sys_role;
+---------+-----------+------------+
| role_id | role_name | role_state |
+---------+-----------+------------+
| 1 | 总监 | NULL |
| 3 | 总监秘书 | NULL |
+---------+-----------+------------+
2 rows in set (0.00 sec)

SQL:

Hibernate:
select
user0_.user_id as user_id1_3_0_,
user0_.user_name as user_nam2_3_0_,
user0_.user_state as user_sta3_3_0_
from
sys_user user0_
where
user0_.user_id=?
Hibernate:
delete
from
sys_user_role
where
user_id=?
Hibernate:
delete
from
sys_user
where
user_id=?

结果:

mysql> select * from sys_user;
Empty set (0.00 sec) mysql> select * from sys_role;
+---------+-----------+------------+
| role_id | role_name | role_state |
+---------+-----------+------------+
| 1 | 总监 | NULL |
| 3 | 总监秘书 | NULL |
+---------+-----------+------------+
2 rows in set (0.00 sec) mysql> select * from sys_user_role;
Empty set (0.00 sec)

3.进阶操作

1.inverse属性:

   一般开发中遇到多对多的关系总有一方放弃维护关系,至于是哪一方要看具体的业务需求。可以在代码中放弃维护,也可以在配置文件中放弃维护。例如录入员工时需要为员工指定所属角色,那么业务方向就是由员工维护角色,角色不需要维护与员工的关系。

  • 代码中放弃维护角色:
    /**
*测试保存(多对多)
*/
@Test
public void fun1() {
//1.获取session
Session session = HibernateUtil.openSession();
//2.开启事务
Transaction tx = session.beginTransaction();
//3.构造数据(张三-总监、经理,李四---总监)
User u1 = new User();
u1.setUser_name("张三");
User u2 = new User();
u2.setUser_name("李四"); Role r1 = new Role();
r1.setRole_name("总监");
Role r2 = new Role();
r2.setRole_name("经理"); u1.getRoles().add(r1);
u1.getRoles().add(r2);
u2.getRoles().add(r1);
//角色放弃维护与员工的关系
// r1.getUsers().add(u1);
// r1.getUsers().add(u2);
// r2.getUsers().add(u1); session.save(r1);
session.save(r2);
session.save(u1);
session.save(u2);
//4.提交数据
tx.commit();
//5.关闭session
session.close();
}
  • Role.hbm.xml配置文件中放弃维护关系inverse属性为true即是放弃维护关系

2.级联操作  cascade属性

save-update :级联保存或更新

delete:级联删除

all:等于save-update+delete

1.级联保存或者更新:

  例如我们新增一个角色并且给张三赋予新角色的代码如下:

    @Test
public void fun2() {
//1.获取session
Session session = HibernateUtil.openSession();
//2.开启事务
Transaction tx = session.beginTransaction();
//3.构造数据(张三-总监、经理,李四---总监)
User u1 = session.get(User.class, 1l);
Role r3 = new Role();
r3.setRole_name("太监222"); session.save(r3);//保存新角色 u1.getRoles().add(r3);//u1处于持久态,因此不用执行更新语句也可以更新 //4.提交数据
tx.commit();
//5.关闭session
session.close();
}

 

 我们希望在更新user的时候会级联保存角色,也就是省区一行session.save(r3)对象。

(1)修改User.hbm.xml

(2)将代码保存角色的那一行代码注释掉

(3)测试并查看SQL:

Hibernate:
select
user0_.user_id as user_id1_3_0_,
user0_.User_name as User_nam2_3_0_,
user0_.user_state as user_sta3_3_0_
from
sys_user user0_
where
user0_.user_id=?
Hibernate:
select
roles0_.user_id as user_id1_4_0_,
roles0_.role_id as role_id2_4_0_,
role1_.role_id as role_id1_2_1_,
role1_.role_name as role_nam2_2_1_,
role1_.role_state as role_sta3_2_1_
from
sys_user_role roles0_
inner join
sys_role role1_
on roles0_.role_id=role1_.role_id
where
roles0_.user_id=?
Hibernate:
insert
into
sys_role
(role_name, role_state)
values
(?, ?)
Hibernate:
insert
into
sys_user_role
(user_id, role_id)
values
(?, ?)

2.级联删除:

修改User.hbm.xml,开启级联删除:

测试代码:(会级联去删除角色表,如果角色表对应记录被其他用户引用会报错)

    /**
*删除张三,查看级联删除角色
*/
@Test
public void fun4() {
//1.获取session
Session session = HibernateUtil.openSession();
//2.开启事务
Transaction tx = session.beginTransaction();
//3.构造数据(张三-总监、经理,李四---总监)
User u1 = session.get(User.class, 5l);
session.delete(u1); //4.提交数据
tx.commit();
//5.关闭session
session.close();
}

查看发出的SQL:

Hibernate:
select
user0_.user_id as user_id1_3_0_,
user0_.User_name as User_nam2_3_0_,
user0_.user_state as user_sta3_3_0_
from
sys_user user0_
where
user0_.user_id=?
Hibernate:
select
roles0_.user_id as user_id1_4_0_,
roles0_.role_id as role_id2_4_0_,
role1_.role_id as role_id1_2_1_,
role1_.role_name as role_nam2_2_1_,
role1_.role_state as role_sta3_2_1_
from
sys_user_role roles0_
inner join
sys_role role1_
on roles0_.role_id=role1_.role_id
where
roles0_.user_id=?
Hibernate:
delete
from
sys_user_role
where
user_id=?
Hibernate:
delete
from
sys_role
where
role_id=?
Hibernate:
delete
from
sys_role
where
role_id=?
Hibernate:
delete
from
sys_user
where
user_id=?

总结:

    O 对象            两方都使用集合.
R 关系型数据库 使用中间表.至少两列.作为外键引用两张表的主键.
M 映射文件 多: <set name="" table="中间表名" >
<key column="别人引用我" />
<man-to-many class="" column="我引用别人的" />
</set> 操作:操作管理级别属性.
cascade: 级联操作
减少我们书写的操作代码.
none(默认值) 不级联
save-update: 级联保存
delete: 级联删除
all: 级联保存+级联删除
结论: 可以使用save-update.不推荐使用delete. 也可以不用cascade.
inverse: 反转关系维护
属于性能优化.必须选择一方放弃维护主键关系.哪方放弃要看业务方向.

补充:多对多的时候经常用到查询,比如上面查询用户ID为1的用户具有的角色

  用HQL判断两个实体间是否存在一对多关系,用的  in elements, 注意in elements 只能用于where 从句中

语法如下:

    @Test
public void fun5() {
// 1.获取session
Session session = HibernateUtil.openSession(); String hql = "from Role r where ? in elements(r.users)";
Query query = session.createQuery(hql); User user = new User();
user.setUser_id(1L);
query.setParameter(0, user); List<Role> roles = query.list();
System.out.println(roles);
}

查看SQL语句如下:

Hibernate:
select
role0_.role_id as role_id1_0_,
role0_.role_name as role_nam2_0_,
role0_.role_state as role_sta3_0_
from
sys_role role0_
where
? in (
select
users1_.user_id
from
sys_user_role users1_
where
role0_.role_id=users1_.role_id
)
Hibernate:
select
users0_.role_id as role_id2_2_0_,
users0_.user_id as user_id1_2_0_,
user1_.user_id as user_id1_1_1_,
user1_.User_name as User_nam2_1_1_,
user1_.user_state as user_sta3_1_1_
from
sys_user_role users0_
inner join
sys_user user1_
on users0_.user_id=user1_.user_id
where
users0_.role_id=?
Hibernate:
select
users0_.role_id as role_id2_2_0_,
users0_.user_id as user_id1_2_0_,
user1_.user_id as user_id1_1_1_,
user1_.User_name as User_nam2_1_1_,
user1_.user_state as user_sta3_1_1_
from
sys_user_role users0_
inner join
sys_user user1_
on users0_.user_id=user1_.user_id
where
users0_.role_id=?

hibernate的多对多关联映射的更多相关文章

  1. 8.Hibernate的多对多关联映射

    1.创建如下数据库脚本 --1.1 项目表 create table PROJECT ( proid ) not null, proname ) ) ; --1.2 项目表主键 alter table ...

  2. 【SSH系列】Hibernate映射 -- 多对多关联映射

         映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论 ...

  3. (Hibernate进阶)Hibernate映射——多对多关联映射(八)

    多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数 ...

  4. Hibernate(六)——多对多关联映射

    前面几篇文章已经较讲解了三大种关联映射,多对多映射就非常简单了,不过出于对关联映射完整性的考虑,本文还是会简要介绍下多对多关联映射. 1.单向多对多关联映射 情景:一个用户可以有多个角色,比如数据录入 ...

  5. hibernate之关于使用连接表实现多对一关联映射

    [Hibernate]之关于使用连接表实现多对一关联映射 在我们项目使用中採用中间表最多的一般就是多对一,或者是多对多,当然一对一使用中间表也是能够的,可是这样的几率通常少之又少!所以这里重点介绍多对 ...

  6. 一口一口吃掉Hibernate(六)——多对多关联映射

    今天来说说hibernate中的多对多关联映射,多对多关联映射涉及到单向映射和双向映射2种. 首先举个多对多关联例子:用户User和角色Role,一个用户可以属于多个角色,一个角色可以有多个用户.这就 ...

  7. Hibernate ManyToOne Mappings 多对一关联映射

    Hibernate ManyToOne Mappings 多对一关联映射 Hibernate框架的使用步骤: 1.创建Hibernate的配置文件(hibernate.cfg.xml)2.创建持久化类 ...

  8. 【SSH进阶之路】Hibernate映射——多对多关联映射(八)

    上篇博文[SSH进阶之路]Hibernate映射——一对多关联映射(七),我们介绍了一对多关联映射,它是多对多关联映射的基础. 多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接 ...

  9. java之hibernate之单向的多对多关联映射

    这篇 单向的多对多关联映射 1.如何在权限管理中,角色和权限之间的关系就是多对多的关系,表结构为: 2.类结构 Permission.java public class Permission impl ...

随机推荐

  1. c# winform调用摄像头识别二维码

    首先我们需要引用两个第三方组件:AForge和zxing. Aforge是摄像头操作组件,zxing是二维码识别组件.都是开源项目.避免重复造轮子. 其实一些操作代码我也是参照别人的,若侵犯您的版权, ...

  2. Daily Scrum NO.7

    工作概况 今日由于时间比较充裕,没有编译作业的干扰,团员们的进度喜人.线程池.动态爬取.异常清理这三个主要开发工作已经步入尾声.其中线程池开发工作的代码已经签入,现主要在测试和优化.动态爬取今日也签入 ...

  3. Uploadify提示-Failed,上传不了文件,跟踪onUploadError事件,errorMsg:2156 SecurityError Error #2156 null

    在使用Uploadify上传文件时,提示-Failed,上传不了文件 折腾中.....,没有结果.....%>_<%... 于是跟踪onUploadError事件,发现 errorMsg: ...

  4. JAVA面对对象(一)——封装

    1.封装思想:将对象的属性和行为封装起来的载体是类,类通常对客户隐藏其实现的细节 2.封装就是将属性私有化(private),并提供公共的方法(public)访问私有属性 3.通过封装,实现对属性数据 ...

  5. dispatch_block_t

    通常我写一个不带参数的块回调函数是这样写的 在 . h 头文件中 定义类型 typedef void (^leftBlockAction)(); 在定义一个回调函数 -(void)leftButton ...

  6. 第十一周(11.24-12.01)----ptim测试程序运行速度

    我在dos下用ptime指令对分数运算(http://www.cnblogs.com/YangXiaomoo/p/6095583.html)的运行时间进行了测试.测试结果一般都在0.212-0.217 ...

  7. PAT 甲级 1051 Pop Sequence

    https://pintia.cn/problem-sets/994805342720868352/problems/994805427332562944 Given a stack which ca ...

  8. 【转】mysql优化步骤

    作者:zhuqz链接:https://www.zhihu.com/question/19719997/answer/81930332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

  9. js生成hash序列

    炒鸡简单的js生成hash序列的方法.如下: function createHash (hashLength) { if (!hashLength || typeof(Number(hashLengt ...

  10. python_面向对象小试题

    打印啥? class Animal(object): hobby = "eat" def run(self): print(self.hobby) return self.hobb ...