假设应用场景如下:Teacher与Student是多对多的关系,其中,Teacher类对应teacher表如下:
CREATE TABLE `teacher` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
Student类对应student表如下:
CREATE TABLE `student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
中间表teacher_student表如下:
CREATE TABLE `teacher_student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`teacher_id` bigint(20) NOT NULL ,
`student_id` bigint(20) NOT NULL ,
PRIMARY KEY (`id`),
KEY `fk_reference_50` (`teacher_id`),
CONSTRAINT `fk_reference_50` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`),
KEY `fk_reference_60` (`teacher_id`),
CONSTRAINT `fk_reference_60` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`teacher_id` bigint(20) NOT NULL ,
`student_id` bigint(20) NOT NULL ,
PRIMARY KEY (`id`),
KEY `fk_reference_50` (`teacher_id`),
CONSTRAINT `fk_reference_50` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`),
KEY `fk_reference_60` (`teacher_id`),
CONSTRAINT `fk_reference_60` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
Student类如下:
public class Student{
//对应的教师集合
private Set<Teacher> teachers = new HashSet<Teacher>();
/*
* @ManyToMany 注释表示Student是多对多关系的一边,mappedBy 属性定义了Student 为双向关系的维护端
*/
@ManyToMany(mappedBy = "students")
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
}
//对应的教师集合
private Set<Teacher> teachers = new HashSet<Teacher>();
/*
* @ManyToMany 注释表示Student是多对多关系的一边,mappedBy 属性定义了Student 为双向关系的维护端
*/
@ManyToMany(mappedBy = "students")
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
}
说明
1、该类经过简化,没有列出全部代码,在此我们只关注ManyToMany注解及其属性设置。
其他属性说明参加上篇文章:如何使用JPA注解标注一对一的关系
public class Teacher implements Serializable {
// 对应的学生集合
private Set<Student> students = new HashSet<Student>();
/*
* @ManyToMany 注释表示Teacher 是多对多关系的一端。
* @JoinTable 描述了多对多关系的数据表关系,name属性指定中间表名称。
* joinColumns 定义中间表与Teacher 表的外键关系,中间表teacher_student的teacher_id 列是 teacher 表的主键列对应的外键列。
* inverseJoinColumns 属性定义了中间表与另外一端(Student)的外键关系。
*/
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinTable(name = "teacher_student",
joinColumns ={@JoinColumn(name = "teacher_id", referencedColumnName = "id") },
inverseJoinColumns = { @JoinColumn(name = "student_id", referencedColumnName = "id")
})
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
// 对应的学生集合
private Set<Student> students = new HashSet<Student>();
/*
* @ManyToMany 注释表示Teacher 是多对多关系的一端。
* @JoinTable 描述了多对多关系的数据表关系,name属性指定中间表名称。
* joinColumns 定义中间表与Teacher 表的外键关系,中间表teacher_student的teacher_id 列是 teacher 表的主键列对应的外键列。
* inverseJoinColumns 属性定义了中间表与另外一端(Student)的外键关系。
*/
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinTable(name = "teacher_student",
joinColumns ={@JoinColumn(name = "teacher_id", referencedColumnName = "id") },
inverseJoinColumns = { @JoinColumn(name = "student_id", referencedColumnName = "id")
})
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
说明:
1、@JoinTable
@JoinTable注解定义了联接表的表名,连接列数组,以及invers连接列数组。invers连接列数组是关联表中关联到student表主键的列(the “other side”)。
被关联端(Student)不必也不能描述物理映射:只需要一个简单的mappedBy参数,该参数包含了主体端(Teacher)的属性名,这样就绑定了双方的关系。
默认值:
和其它许多注解一样,在多对多关联中很多值是自动生成,当双向多对多关联中没有定义任何物理映射时,Hibernate根据以下规则生成相应的值:
关联表名:主表表名+下划线+从表表名;
关联到主表的外键名:主表名+下划线+主表中的主键列名;
关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名。
以上规则对于双向一对多关联同样一样。