基于xml的many-to-many双向关联的关键配置:
many2many(xml):双向关联
|--->model
|--->Student
|--->private Set<Course> courses = new HashSet<Student>();
|--->Course
|--->private Set<Student> students = new HashSet<Course>();
|--->*.hbm.xml
|--->Student.hbm.xml
|---><set name="courses" table="STUDENT_COURSE_1" cascade="save-update,remove">
<key column="STUDENT_ID" />
<many-to-many column="COURSE_ID" class="Course" />
</set>
|--->Course.hbm.xml
|---><set name="students" table="STUDENT_COURSE_1" cascade="save-update,remove" inverse="true">
<key column="COURSE_ID" />
<many-to-many column="STUDENT_ID" class="Student" />
</set>
|--->hibernate.cfg.xml
|---><mapping resource="model/Student.hbm.xml" />
|---><mapping resource="model/Course.hbm.xml" />
注意到Student.hbm.xml和Course.hbm.xml的<set>元素其子元素<key> <many-to-many> 刚好相反,而其中一个有inverse=true的属性。
inverse映射属性究竟是什么:
双向关联只是在两端正确的设置引用,而hibernate并没有足够的信息去正确地执行insert和update语句以避免违反数据库约束。inverse属性告诉hibernate忽略这一端,而把这一端看作另一端的镜像mirror,也可以理解为该端被人为地指定为负的导航方向了。
只需记住一个rule:双向关联必须有一端被设置为inverse。
在一对多的双向关联中,它必须是多(many)的那一端;而多对多的双向关联中,则因为两端并没有差别,所以在哪一端设置为inverse完全取决于自己。
基于annotation的many-to-many双向关联:
先看Student实体类:
package model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@Entity
@Table(name="STUDENTS_11")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.TABLE)
@Column(name="STUDENT_ID")
private Long student_id;
@Column(name="SNAME")
private String sname;
@Column(name="GENDER")
private String gender;
@Column(name="AGE")
private int age;
@ManyToMany(targetEntity=Course.class)
@JoinTable(name="STUDENT_COURSE_11",schema="hibernate",
joinColumns={@JoinColumn(name="STUDENT_ID")},
inverseJoinColumns={@JoinColumn(name="COURSE_ID")}
)
@Cascade(value={CascadeType.SAVE_UPDATE,CascadeType.REMOVE})
private Set<Course> courses = new HashSet<Course>();
public Long getStudent_id() {
return student_id;
}
public void setStudent_id(Long student_id) {
this.student_id = student_id;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
Course实体类:
package model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name="COURSES_11")
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.TABLE)
@Column(name="COURSE_ID")
private Long course_id;
@Column(name="CNAME")
private String cname;
@ManyToMany(mappedBy="courses")
private Set<Student> students = new HashSet<Student>();
public Long getCourse_id() {
return course_id;
}
public void setCourse_id(Long course_id) {
this.course_id = course_id;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
对比两个Entity classes可知基于annotation的many-to-many双向关联的关键配置如下:
many2many(xml):双向关联
|--->model
|--->Student
|--->private Set<Course> courses = new HashSet<Student>();
@ManyToMany(TargetEntity=Course.class)
@JoinTable(name="STUDENT_COURSE_11",schema="hibernate",
joinColumns={@JoinColumn(name="STUDENT_ID")},
inverseJoinColumns={@JoinColumn(name="COURSE_ID")}
)
@Cascade(value={CascadeType.SAVE_UPDATE,CascadeType.REMOVE})
|--->Course
|--->private Set<Student> students = new HashSet<Course>();
@ManyToMany(mappedBy="courses")
|--->hibernate.cfg.xml
|---><mapping class="model.Student" />
|---><mapping class="model.Course" />
注意这里在负的导航方向一端(inverseJoinColumns={@JoinColumn(name="COURSE_ID")}指明了哪一端为负),其集合字段被注解为@ManyToMany(mappedBy="courses").