JPA进阶(二)-对象关系映射

JPA进阶-映射

一对多关系

单向

单向一对多用得比较少(性能差),但是还是需要了解,单向一对多其实就是在主表中添加ManyToOne的注解即可

双向

同时在两个类中添加注解,在使用双向连接的时候,主从表外键名称必须一致

这里设计主表为Department

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
51
52
53
54
55
56
57
package com.ifueen.domian;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "department")
public class Department {
@Id
@GeneratedValue
private Long id;
private String name;

public Department() {
}

@Override
public String toString() {
return "Department{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<Employee> getList() {
return list;
}

public void setList(List<Employee> list) {
this.list = list;
}

@OneToMany(cascade = CascadeType.ALL,mappedBy = "department",fetch = FetchType.LAZY,orphanRemoval = true)
//@JoinColumn(name = "department_id")
List<Employee> list= new ArrayList<Employee>();




}

从表Employee的设计

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
package com.ifueen.domian;


import javax.persistence.*;

@Entity
@Table(name = "employee")
public class Employee {
public Employee() {
}

@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'';
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Department department;

public Department getDepartment() {
return department;
}

public void setDepartment(Department department) {
this.department = department;
}
}

两个表的实体类创建好之后,测试以下,如果没有报错那么就表示成功了

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
/**
* 测试添加功能是否成功
*
*/
@Test
public void test1(){
EntityManager jpa = JPAUtil.getJpa();
Employee employee = new Employee();
employee.setName("库布里奇");

Employee employee1 = new Employee();
employee1.setName("希区柯克");

Department department = new Department();
department.setName("电影");

/* department.getList().add(employee);
department.getList().add(employee1);*/

employee.setDepartment(department);
employee1.setDepartment(department);

EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(department);
jpa.persist(employee);
jpa.persist(employee1);
transaction.commit();
jpa.close();
}

级联操作

为什么需要将两张表关联起来呢?因为将它们进行关联以后,我们便可以进行级联操作,虽然平时用的可能不是太多

级联添加

进行主表的添加,只需要设置好从表的数据,那么从表也会将数据添加进去

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
/**
* 级联添加
* 双方都需要建立连接和维护
* 在添加的时候只需要添加主表,从表的数据也会随之添加
*/
@Test
public void test2(){
EntityManager jpa = JPAUtil.getJpa();
Employee employee = new Employee();
employee.setName("库布里奇");

Employee employee1 = new Employee();
employee1.setName("希区柯克");

Department department = new Department();
department.setName("电影");

department.getList().add(employee);
department.getList().add(employee1);

employee.setDepartment(department);
employee1.setDepartment(department);

EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(department);
transaction.commit();
jpa.close();
}

级联删除(慎用!容易遭到整个项目组的毒打)

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* 级联删除
*/
@Test
public void test3(){

EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
Department department = jpa.find(Department.class, 1L);
System.out.println(department);
jpa.remove(department);
transaction.commit();
jpa.close();
}

/**
* 级联删除,通过主表删除从表相关的数据
*/
@Test
public void test4(){

EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();


String hql = "update Employee e set e.department = null";
Query query = jpa.createQuery(hql);
query.executeUpdate();

Department department = jpa.find(Department.class, 2L);
jpa.remove(department);

transaction.commit();
jpa.close();
}

/**
* 直接删除多方,不经过主表,主表不会受到影响
*/
@Test
public void test5(){

EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();

Employee employee = jpa.find(Employee.class, 5L);
jpa.remove(employee);
transaction.commit();
jpa.close();
}

/**
* 级联删除,使用脏数据更新,通过主表删除从表相对应的数据
*/
@Test
public void test6(){

EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
Department department = jpa.find(Department.class, 2L);
//脏数据更新
department.getList().clear();

transaction.commit();
jpa.close();
}

多对多关系

单向多对多

单向的多对多其实用的都挺少的,而且使用单向,建表sql语句的冗余度也挺高的,所以这里不进行总结,如果需要了解,可以自行网上搜索一下

双向多对多

这里实现一个案例,通过案例来协助掌握双向多对多

两个表,user和role,分别对应导演和作品的,使他们之间进行关联起来

User表设计

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
51
52
53
54
package com.ifueen.domian;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "user")
public class User {

@Id
@GeneratedValue
private Long id;
private String name;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<Role> getRoles() {
return roles;
}

public void setRoles(List<Role> roles) {
this.roles = roles;
}

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "t_user_role",joinColumns = {@JoinColumn(name = "user_id")},inverseJoinColumns = {@JoinColumn(name = "role_id")})
private List<Role> roles = new ArrayList<Role>();

public User() {
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

Role表设计

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
51
52
53
package com.ifueen.domian;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue
private Long id;
private String name;

public Role() {
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<User> getUsers() {
return users;
}

public void setUsers(List<User> users) {
this.users = users;
}

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "t_user_role",joinColumns = {@JoinColumn(name = "role_id")},inverseJoinColumns = {@JoinColumn(name = "user_id")})
private List<User> users = new ArrayList<User>();

@Override
public String toString() {
return "Role{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

两张表的实体类设计好,现在测试

1
2
3
4
5
6
7
/**
* 多对多连接,生成表
*/
@Test
public void test(){
EntityManager jpa = JPAUtil.getJpa();
}

表结构就搭建好了

下面就可以写功能进行测试

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* 多对多连接,添加
*/
@Test
public void test1(){
EntityManager jpa = JPAUtil.getJpa();
User user = new User();
user.setName("黑泽明");

User user1 = new User();
user1.setName("库布里克");

User user2 = new User();
user2.setName("诺兰");

Role role = new Role();
role.setName("七武士");

Role role1 = new Role();
role1.setName("2001太空漫步");

Role role2 = new Role();
role2.setName("星际穿越");

Role role3 = new Role();
role3.setName("黑暗骑士");

//维护关系
user.getRoles().add(role);
user1.getRoles().add(role1);
user2.getRoles().add(role2);
user2.getRoles().add(role3);

EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(user);
jpa.persist(user1);
jpa.persist(user2);
jpa.persist(role);
jpa.persist(role1);
jpa.persist(role2);
jpa.persist(role3);

transaction.commit();
jpa.close();

}

/**
* 查询
*/
@Test
public void test2(){
EntityManager jpa = JPAUtil.getJpa();
User user = jpa.find(User.class, 3L);
System.out.println(user);
List<Role> roles = user.getRoles();
roles.forEach(System.out::println);
jpa.close();


}

/**
* 多对多连接,只需要添加一张表
*/
@Test
public void test3(){
EntityManager jpa = JPAUtil.getJpa();
User user = new User();
user.setName("黑泽明");

User user1 = new User();
user1.setName("库布里克");

User user2 = new User();
user2.setName("诺兰");

Role role = new Role();
role.setName("七武士");

Role role1 = new Role();
role1.setName("2001太空漫步");

Role role2 = new Role();
role2.setName("星际穿越");

Role role3 = new Role();
role3.setName("黑暗骑士");

//维护关系
user.getRoles().add(role);
user1.getRoles().add(role1);
user2.getRoles().add(role2);
user2.getRoles().add(role3);

EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(user);
jpa.persist(user1);
jpa.persist(user2);

transaction.commit();
jpa.close();

}


/**
* 删除,没有配置级联删除
*
*/
@Test
public void test4(){
EntityManager jpa = JPAUtil.getJpa();
jpa.getTransaction().begin();
User user = jpa.find(User.class, 3L);
jpa.remove(user);
jpa.getTransaction().commit();
jpa.close();
}

注意,在使用除了添加功能的时候,需要在生成组策略中配置为,如果value=”create”的话每次查询都会把全部数据删除完,真是血的教训!!

❤赏点钱让我买杯快乐水8❤