多对多关联,不论是在单项,还是在双向的时候,数据库模型中都只是用中间表,变化的只是我们的变成模型。以下代码以学生和老师的关联关系为例。(由于数据库模型没有变化,所以生成的建表语句最后一起给出。)
一:多对多单向关联
单项关联中,从老师可以找到对应的学生,但是从学生找不到对应的老师。
1.1:Annotation方式:
代码如下:
Teacher.java:
@Entity
@Table(name="t_teacher")
public class Teacher {
private int id;
private String name;
private Set<Student> students = new HashSet<Student>();
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany
@JoinTable(name="t_s",
joinColumns={@JoinColumn(name="t_id")},
inverseJoinColumns={@JoinColumn(name="s_id")}
)
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
多对多关联中,我们使用@JoinTable来控制中间表的相关信息的设置(表名,列名的对应关系全部在此处设置)。
Student.java:
@Entity
@Table(name="t_student")
public class Student {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}<span style="font-weight: bold; "> </span>
1.2:XML方式:
由于现在只是从Teacher可以的到Student,但是反过来不可以,所以,Student.hbm.xml是就是常规设置即可,而在Teacher.hbm.xml我们需要设置多到多的当相关联。代码如下:
Teacher.hbm.xml:
<hibernate-mapping package="com.zxb.model">
<class name="Teacher">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" column="name" />
<set name="student" table="t_s">
<key column="t_id"></key>
<many-to-many class="Student" column="s_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
注意:此处的<set>中的key指定的column就是我们在Annotation中指定的@JoinColumns中指定的列名对应,而many-to-many中指定的column就是和Annotation中指定的inverseJoinColumns中指定的列名对应。
二:多对多双向关联
2.1:Annotation方式:
由于现在是双向关联,需要我们可以从Studnet找到对应的老师,所以在上面代码的Annotation版本的基础上,所以的改变在Studnet.java中。改变后代码如下:
@Entity
@Table(name="t_student")
public class Student {
private int id;
private String name;
private Set<Teacher> teachers = new HashSet<Teacher>();
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany(mappedBy="students")
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
上面代码中,由于是双向的关联,而我们在Teacher.java中已经设置了详细的关联信息,所以,此处我们只需要使用mappedBy来说明关联关系已经通过对方类的studnets属性来设置了即可。
2.2:XML方式:
由于现在是双向关联,需要我们可以从Studnet找到对应的老师,所以在上面代码的XML版本的基础上,所以的改变在Studnet.hbm.xml中。改变后代码如下:
<hibernate-mapping package="com.zxb.model">
<class name="Student">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" column="name" />
<set name="teachers" table="t_s">
<key column="s_id"></key>
<many-to-many class="Teacher" column="t_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
注意,在此处的Set集合里面相关属性的设置刚好是和我们的Teacher.hbm.xml是相反的。
测试输出:
09:49:36,472 DEBUG SchemaExport:377 -
create table Student (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
09:49:36,527 DEBUG SchemaExport:377 -
create table Teacher (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
09:49:36,576 DEBUG SchemaExport:377 -
create table t_s (
t_id integer not null,
s_id integer not null,
primary key (s_id, t_id)
)
09:49:36,694 DEBUG SchemaExport:377 -
alter table t_s
add index FK1BF68E573C0C (t_id),
add constraint FK1BF68E573C0C
foreign key (t_id)
references Teacher (id)
09:49:37,060 DEBUG SchemaExport:377 -
alter table t_s
add index FK1BF68F4237E06 (s_id),
add constraint FK1BF68F4237E06
foreign key (s_id)
references Student (id)
09:49:37,227 INFO SchemaExport:268 - schema export complete
从上面可以看出,多对多通过中间表关联,而且关联关系设置良好。