hibernate的多对多关联映射
在我们实际项目中,多对多的情况也时长存在,比如最常见的就是系统管理的五张表,如下面的一个结构:
在本文学习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=?