对于数据表多对多对联只能用外键表进行管理关联关系。在Hibernate中用@ManyToMany(targetEntity=xxx.class)进行定义关联关系。
//映射连接表,指定连接表的表名为xxxx
@JoinTable(name="xxx",
//映射连接表中名为xxxx的外键列,该列参照当前实体的主键列
joinColumns=@JoinColumn(name="xxx",referencedColumnName="xxx"),
//映射连接表中名为xxxx的外键列,指定连接表的关联实体对应表中的xxxx外键列
inverseJoinColumns=@JoinColumn(name="xxxx",referencedColumnName="xxxx"))
定义关联关系的方式如上所述。
接下来贴出student实体与course实体的代码。这两个实体就是典型的多对多关联。
Stuident实体:
@Entity
@Table(name="student")
public class Student {
//主键,学号
@Id@Column(name="stu_num")
privateString stu_num;
......
@ManyToMany(targetEntity=Course.class)//定义当前实体所有关联的Course实体
//映射连接表,指定连接表的表名为course_student
@JoinTable(name="course_student",
//映射连接表中名为stu_num的外键列,该列参照当前试题的主键列
joinColumns=@JoinColumn(name="stu_num",referencedColumnName="stu_num"),
//映射连接表中名为cou_id的外键列,指定连接表的关联实体对应表中的cou_id外键列
inverseJoinColumns=@JoinColumn(name="cou_id",referencedColumnName="cou_id"))
privateSet<Course> course = new HashSet<>();
//省略getter和setter方法
}
Course实体:
@Entity
@Table(name="course")
public class Course {
@Id@Column(name="cou_id")//主键列
privateString cou_id;
..........
@ManyToMany(targetEntity=Student.class)//定义当前实体所有关联的student实体
//映射连接表,指定连接表的表名为course_student
@JoinTable(name="course_student",
//映射连接表中名为cou_id的外键列,该列参照当前试题的主键列
joinColumns=@JoinColumn(name="cou_id",referencedColumnName="cou_id"),
//映射连接表中名为stu_num的外键列,指定连接表的关联实体对应表中的stu_num外键列
inverseJoinColumns=@JoinColumn(name="stu_num",referencedColumnName="stu_num"))
privateSet<Student> student = new HashSet<>();
//省略getter和setter方法
}
一般来说,定义了上面两个实体后,当你数据库未创建相关数据表时,Hibernate会自动帮你生成对应的数据表。当然还会自动帮你创建外键表course_student。
如下是运行程序时,Hibenate自动生成数据表的sql语句:
Hibernate:
create table student (
stu_num varchar(255) not null,
....
primary key (stu_num)
) ENGINE=InnoDB
Hibernate:
create table course (
cou_id varchar(255) not null,
.....
primary key (cou_id)
) ENGINE=InnoDB
Hibernate:
create table course_student (
evalue varchar(255),
score float,
stu_num varchar(255) not null,
cou_id varchar(255) not null,
primary key (stu_num, cou_id)
) ENGINE=InnoDB
Hibernate:
alter table course_student
add constraint FKne34exyo39iajeiyhpredxe0j
foreign key (stu_num)
references student (stu_num)
Hibernate:
alter table course_student
add constraintFKs185u4fs0jmr6y4ty13cgv81u
foreign key (cou_id)
references course (cou_id)
这样就生成了三张数据表,但是外键表的字段只有相应的外键形成联合主键
那么我现在想要外键表添加两个字段,一个是对学生成绩记录的字段,一个是对学生成绩评估的字段。那么通过HIbernate自动生成外键表示不可能达到我们所要的效果的。于是我们所需要做得是,创建多一个实体类CourseStudent,该实体类映射course_student数据表。
然后在该实体中,创建联合主键,映射到对应实体上。然后再添加我们所想要添加的字段。
主要代码如下:
@Entity
@Table(name="course_student")
public class CourseStudent implements Serializable{
//定义关联student实体
@ManyToOne(targetEntity=Student.class)
//映射名为stu_num的外键列,参照student的stu_num列
@JoinColumn(name="stu_num",referencedColumnName="stu_num")
@Id
private Studentstudent;
//定义关联Course实体
@ManyToOne(targetEntity=Course.class)
//映射名为cou_id的外键列,参照COurse的cou_id列
@JoinColumn(name="cou_id",referencedColumnName="cou_id")
@Id
private Course course;
//学生成绩
@Column(name="score")
private float score;
//学生评价
@Column(name="evalue")
private String evalue;
//无参构造器
publicCourseStudent(){}
//初始化全部成员变量的构造器
publicCourseStudent(Student student,Course course){
this.student= student;
this.course= course;
}
//重写equals()方法,根据student、course判断是否相等
public boolean equals(Objectobj){
if(this ==obj){
returntrue;
}
if(obj !=null && obj.getClass() == CourseStudent.class){
CourseStudenttarget = (CourseStudent) obj;
returnthis.student.equals(target.getStudent())
&&this.course.equals(target.getCourse())
&&this.score==(target.getScore())
&&this.evalue.equals(target.getEvalue());
}
returnfalse;
}
//重写hashCode()方法,根据student、Course计算haseCode值
public int hashCode(){
return(this.course== null ?0:this.course.hashCode())*31*31+
(this.student== null? 0:this.student.hashCode())*31;
}
//省略getter和setter方法
}
因为该实体是联合主键,我们得实现Serializable接口,重写equals()方法和hashCode()方法。
这样一运行程序,Hibernate生成的sql语句中就会有这样的语句:
Hibernate:
create table course_student (
evalue varchar(255),
score float,
stu_num varchar(255) not null,
cou_id varchar(255) not null,
primary key (stu_num, cou_id)
) ENGINE=InnoDB
这就说明我们这样创建外键表对应的实体类是正确的,其Student实体与Course实体关联关系没有改变。