Student.java
1 package cn.itcast.bean;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 import javax.persistence.CascadeType;
7 import javax.persistence.Column;
8 import javax.persistence.Entity;
9 import javax.persistence.GeneratedValue;
10 import javax.persistence.Id;
11 import javax.persistence.JoinColumn;
12 import javax.persistence.JoinTable;
13 import javax.persistence.ManyToMany;
14
15 @Entity
16 public class Student {
17 private Integer id;
18 private String name;
19 private Set<Teacher> teachers = new HashSet<Teacher>();
20
21 @Id @GeneratedValue //id作为实体标识符 并且采用数据库的id自增长方式生成主键值
22 public Integer getId() {
23 return id;
24 }
25
26 public void setId(Integer id) {
27 this.id = id;
28 }
29
30 @Column(length = 10, nullable = false)
31 public String getName() {
32 return name;
33 }
34
35 public void setName(String name) {
36 this.name = name;
37 }
38
39 @ManyToMany(cascade = CascadeType.REFRESH)
40 @JoinTable(name = "student_teacher", inverseJoinColumns = @JoinColumn(name = "teacher_id"),
41 joinColumns = @JoinColumn(name = "student_id"))
42 public Set<Teacher> getTeachers() {
43 return teachers;
44 }
45 /*
46 假如不对关联表里的字段做任何设定,那么表里面的字段默认由JPA的实现产品来帮我们自动生成。
47 inverseJoinColumns:inverse中文是反转的意思,但是觉得太恶心了,在JPA里,可以理解为被维护端
48 inverseJoinColumns被维护端外键的定义
49 @JoinColumn:外键,中间表哪个外键名称跟teacher表的主键关联
50 joinColumns:关系维护端的定义
51 */
52
53 public void setTeachers(Set<Teacher> teachers) {
54 this.teachers = teachers;
55 }
56 }
Teacher.java
1 package cn.itcast.bean;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 import javax.persistence.CascadeType;
7 import javax.persistence.Column;
8 import javax.persistence.Entity;
9 import javax.persistence.GeneratedValue;
10 import javax.persistence.Id;
11 import javax.persistence.ManyToMany;
12
13 @Entity
14 public class Teacher {
15 private Integer id;
16 private String name;
17 private Set<Student> students=new HashSet<Student>();
18
19 @Id @GeneratedValue //id作为实体标识符 并且采用数据库的id自增长方式生成主键值
20 public Integer getId() {
21 return id;
22 }
23 public void setId(Integer id) {
24 this.id = id;
25 }
26
27 @Column(length = 10, nullable = false)
28 public String getName() {
29 return name;
30 }
31 public void setName(String name) {
32 this.name = name;
33 }
34
35 @ManyToMany(cascade=CascadeType.REFRESH,mappedBy="teachers")
36 public Set<Student> getStudents() {
37 return students;
38 }
39 /*
40 cascade:
41 CascadeType.PERSIST:级联保存不要,学生没来之前,老师就已经在了
42 CascadeType.MERGE:级联更新不要,把学生的信息改了,没必要修改相应的老师的信息,压根就没这业务需求
43 CascadeType.REMOVE:级联删除更不要,如果双方都设了级联删除,加入删除学生,会删除相应的老师,被删除的老师又
44 跟学生发生千丝万缕的关系,又把一批学生删掉.....没完没了...最终的结果可能是数据里面所有的记录都被清掉
45 所以在多对多关系中,级联删除通常是用不上的
46 这里只需设置级联涮新CascadeType.PERSIST就可以了,事实上refresh方法也很少使用
47 mappedBy: 通过这个属性来说明老师是关系被维护端
48 fetch: 加载行为默认是延迟加载(懒加载),凭Many。 这里不需要设置
49 */
50
51 public void setStudents(Set<Student> students) {
52 this.students = students;
53 }
54 }
ManyToManyTest.java
1 package junit.test;
2
3 import javax.persistence.EntityManager;
4 import javax.persistence.EntityManagerFactory;
5 import javax.persistence.Persistence;
6
7 import org.junit.BeforeClass;
8 import org.junit.Test;
9
10 public class ManyToManyTest {
11
12 @BeforeClass
13 public static void setUpBeforeClass() throws Exception {
14 }
15 @Test
16 public void save() {
17 EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
18 factory.close();
19 }
20
21 }
双向多对多关系是一种对等关系,既然是对等关系,也就是说我们可以人为决定谁是关系维护端,谁是关系被维护端,这里选学生做关系维护端。那么以后就只能通过学生来维护老师跟学生的关系。
假设:
老师A id是1
学生B id是1
那通过什么东西把他们的关系确立起来呢?采用什么来存放他们的关联关系呢?是中间表(关联表)。
学生A和老师B建立起关系,首先要找到关系维护端,是学生,就要通过学生这个关系维护端,学生A.getTeachers().add(Teacher);这样就能把老师跟学生的关系确立起来了。确立起来后,反应在中间表里面就是insert into...一条语句
如果学生A要把老师B开掉,那就要解除关系,也是通过关系维护端学生A,反映在面向对象的操作就是 学生A.getTeachers().remove(Teacher);执行这句代码的时候,在底层JDBC它会对中间表做delete from...语句的操作。
我们都是通过关系维护端来进行操作的,以后在双向关系中一定要找准谁是关系维护端,谁是关系被维护端
@JoinTable的注解有:看图,