Hibernate3 太长,此文紧接Hibernate3
多对多
建表原则:创建中间表,中间表中至少两个字段作为外键,分别指向多对多双方的主键
在Java中采用对象关系来描述:在A中定义B类类型的Set集合,在B类中定义A类类型的Set集合,使用Set集合是为了避免数据的重复。
SQL
1 | CREATE TABLE `sys_role` ( |
创建实体
用户实体
1 | package me.yanrs.domain; |
角色实体
1 | package me.yanrs.domain; |
配置关系映射
User.hbm.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
Role.hbm.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
hibernate.cfg.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
新增
1 | package me.yanrs.service; |
inverse
在多对多的保存操作中,如果进行了双向维护关系,就必须有一方放弃外键的维护权。一般由被动方放弃。用户主动选择角色,角色是被选择的,所以一般角色要放弃外键的维护权。但如果只进行单向维护关系,那么就不需要放弃外键维护权。
级联操作
在多对多中级联操作同样也有方向性的,例如 用户 和 角色 。如果要以用户为主控方,那么就需要在用户的配置文件中进行cascade配置,反之如果要以联系人为主控方,那么就需要在联系人的配置文件中进行cascade配置。
- 保存用户级联角色
Role.hbm.xml配置 (放弃维护外键)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27<?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">
<hibernate-mapping package="me.yanrs.domain">
<class name="Role" table="sys_role">
<id name="role_id">
<generator class="native"></generator>
</id>
<property name="role_name" column="role_name"></property>
<property name="role_memo" column="role_memo"></property>
<!--
set:
name: 关联的另一方的集合的属性名称
table: 中间表的名称
key:
column: 当前对象在中间表中的外键的名称
many-to-many:
class: 关联另一方的类的全路径
column: 关联另一方在中间表中的外键名称
-->
<set inverse="true" name="users" table="sys_user_role">
<key column="role_id"></key>
<many-to-many class="me.yanrs.domain.User" column="user_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
User.hbm.xml配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29<?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">
<hibernate-mapping package="me.yanrs.domain">
<class name="User" table="sys_user">
<id name="user_id">
<generator class="native"></generator>
</id>
<property name="user_code" column="user_code"></property>
<property name="user_name" column="user_name"></property>
<property name="user_password" column="user_password"></property>
<property name="user_state" column="user_state"></property>
<!--
set:
name: 关联的另一方的集合的属性名称
table: 中间表的名称
key:
column: 当前对象在中间表中的外键的名称
many-to-many:
class: 关联另一方的类的全路径
column: 关联另一方在中间表中的外键名称
-->
<set cascade="save-update" name="roles" table="sys_user_role">
<key column="user_id"></key>
<many-to-many class="me.yanrs.domain.Role" column="role_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
测试代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49package me.yanrs.service;
import org.hibernate.Session;
import org.hibernate.Transaction;
import me.yanrs.domain.Customer;
import me.yanrs.domain.Linkman;
import me.yanrs.domain.Role;
import me.yanrs.domain.User;
import me.yanrs.utils.HibernateUtils;
public class one_to_many {
public static void main(String[] args) {
// one2many_base();
// one2many_no_cascade();
// one2many_delete_customer_no_cascade();
//many2many_no_cascade();
many2many_cascade();
}
private static void many2many_cascade() {
Session session = HibernateUtils.getCurrentSession();
//开启事务
Transaction beginTransaction = session.beginTransaction();
User user = new User();
user.setUser_name("user11");
User user2 = new User();
user2.setUser_name("user22");
//创建两个角色
Role role = new Role();
role.setRole_name("role11");
Role role2 = new Role();
role2.setRole_name("role22");
user.getRoles().add(role);
user2.getRoles().add(role2);
session.save(user);
session.save(user2);
//不要忘记提交
beginTransaction.commit();
}
}
- 保存角色级联用户
Role.hbm.xml配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27<?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">
<hibernate-mapping package="me.yanrs.domain">
<class name="Role" table="sys_role">
<id name="role_id">
<generator class="native"></generator>
</id>
<property name="role_name" column="role_name"></property>
<property name="role_memo" column="role_memo"></property>
<!--
set:
name: 关联的另一方的集合的属性名称
table: 中间表的名称
key:
column: 当前对象在中间表中的外键的名称
many-to-many:
class: 关联另一方的类的全路径
column: 关联另一方在中间表中的外键名称
-->
<set cascade="save-update" name="users" table="sys_user_role">
<key column="role_id"></key>
<many-to-many class="me.yanrs.domain.User" column="user_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
User.hbm.xml配置(放弃外键的维护)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29<?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">
<hibernate-mapping package="me.yanrs.domain">
<class name="User" table="sys_user">
<id name="user_id">
<generator class="native"></generator>
</id>
<property name="user_code" column="user_code"></property>
<property name="user_name" column="user_name"></property>
<property name="user_password" column="user_password"></property>
<property name="user_state" column="user_state"></property>
<!--
set:
name: 关联的另一方的集合的属性名称
table: 中间表的名称
key:
column: 当前对象在中间表中的外键的名称
many-to-many:
class: 关联另一方的类的全路径
column: 关联另一方在中间表中的外键名称
-->
<set inverse="true" name="roles" table="sys_user_role">
<key column="user_id"></key>
<many-to-many class="me.yanrs.domain.Role" column="role_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
测试代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51package me.yanrs.service;
import org.hibernate.Session;
import org.hibernate.Transaction;
import me.yanrs.domain.Customer;
import me.yanrs.domain.Linkman;
import me.yanrs.domain.Role;
import me.yanrs.domain.User;
import me.yanrs.utils.HibernateUtils;
public class one_to_many {
public static void main(String[] args) {
// one2many_base();
// one2many_no_cascade();
// one2many_delete_customer_no_cascade();
//many2many_no_cascade();
many2many_cascade();
}
private static void many2many_cascade() {
Session session = HibernateUtils.getCurrentSession();
//开启事务
Transaction beginTransaction = session.beginTransaction();
User user = new User();
user.setUser_name("user11");
User user2 = new User();
user2.setUser_name("user22");
//创建两个角色
Role role = new Role();
role.setRole_name("role11");
Role role2 = new Role();
role2.setRole_name("role22");
role.getUsers().add(user);
role.getUsers().add(user2);
role2.getUsers().add(user);
role2.getUsers().add(user2);
session.save(role);
session.save(role2);
//不要忘记提交
beginTransaction.commit();
}
}
新增
为Role新增一个用户(上面代码中的配置不变【上面的配置是User放弃外键的维护,cascade=”save-update” 】)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38package me.yanrs.service;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.sun.jndi.toolkit.url.Uri;
import me.yanrs.domain.Customer;
import me.yanrs.domain.Linkman;
import me.yanrs.domain.Role;
import me.yanrs.domain.User;
import me.yanrs.utils.HibernateUtils;
public class one_to_many {
public static void main(String[] args) {
// one2many_base();
// one2many_no_cascade();
// one2many_delete_customer_no_cascade();
//many2many_no_cascade();
// many2many_cascade();
add_user_for_role();
}
private static void add_user_for_role() {
Session session = HibernateUtils.getCurrentSession();
//开启事务
Transaction beginTransaction = session.beginTransaction();
User user = new User();
user.setUser_name("new_user");
Role role = session.get(Role.class, 1l);
role.getUsers().add(user);
//持久化对象无需save,直接commit即可
beginTransaction.commit();
}
}删除
删除User的时候,删除对应的角色。配置为User.hbm.xml中cascade=”delete”,Role.hbm.xml中inverse=”true”
1 | package me.yanrs.service; |
多对多的关系主要是靠中间表来维护的,在Hibernate中多对多主要是靠关联的集合来维护的,所以我们只需关心如何操作集合即可。
总结
级联操作的取值可以是save-update、delete、all
inverse的默认值是false,代表维护外键,ture为不维护外键
一对多中
主控方进行级联操作的配置,一的一方应该放弃外键的维护多对多中
必须有一方要放弃主键的维护,一般是被动方放弃主键的维护,主动方进行级联操作的配置