2011-07-04 6:52 一般情況下,多對多的關聯關系是需要中間表的; 情況一:如果中間表僅僅是做關聯用的,它里面僅有2個外鍵做聯合主鍵,則使用ManyToMany(不用寫中間表的Model,只需要寫出兩張主表的model即可) 學生表 @Entity @Table(name = "T_STUDENT") @SequenceGenerator(name = "SEQ_STUDENT", sequenceName = "SEQ_STUDENT") public class Student implements Serializable { private static final long serialVersionUID = 2524659555729848644L; private Long id; private String name; private Date birthday; private int sex; private String address; private Set<Teacher> teacherList; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_STUDENT") @Column(name = "ID", nullable = false, precision = 22, scale = 0) public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column(name = "NAME") public String getName() { return name; } public void setName(String name) { this.name = name; } @Temporal(TemporalType.DATE) @Column(name = "BIRTHDAY") public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Column(name = "sex") public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } @Column(name = "address") public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "T_TEACHER_STUDENT", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "teacher_id")) public Set<Teacher> getTeacherList() { return teacherList; } public void setTeacherList(Set<Teacher> teacherList) { this.teacherList = teacherList; } } 教師表 @Entity @Table(name = "T_TEACHER") @SequenceGenerator(name = "SEQ_TEACHER", sequenceName = "SEQ_TEACHER") public class Teacher implements Serializable { private static final long serialVersionUID = 2297316923535111793L; private Long id; private String name; private int sex; private Set<Student> studentList; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_TEACHER") @Column(name = "ID", nullable = false, precision = 22, scale = 0) public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name = "sex") public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } @ManyToMany(mappedBy = "teacherList", cascade = CascadeType.ALL) public Set<Student> getStudentList() { return studentList; } public void setStudentList(Set<Student> studentList) { this.studentList = studentList; } } hibernate.cfg.xml配置2個class類 <mapping class="com.dvn.li.model.Student"/> <mapping class="com.dvn.li.model.Teacher"/> 測試: SessionFactory sessionFactory = null; Session session = null; try { sessionFactory = HibernateUtil.getSessionFactory(); session = sessionFactory.getCurrentSession(); session.beginTransaction(); Student s = new Student(); s.setName("小豬"); Teacher t = new Teacher(); t.setName("小李"); Set<Teacher> t_set = new HashSet<Teacher>(); t_set.add(t); s.setTeacherList(t_set); session.save(s); } catch (Exception e) { if (session != null) { session.getTransaction().rollback(); } } 測試通過!!! 很簡單吧!注意HibernateUtil.getSessionFactory()的實現如下: public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { // Create the SessionFactory from hibernate.cfg.xml sessionFactory = new AnnotationConfiguration().configure() .buildSessionFactory(); } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } } 如果自己做測試,可以通過SchemaExport導入表結構 SchemaExport export = new SchemaExport(new AnnotationConfiguration() .configure()); export.create(true, true); 情況二:如果中間表不僅僅是做關聯用的,它里面包含了其他字段信息,僅僅靠多對多的關系是搞不定的。 解決方案:多對多的關系拆分為兩個一對多!這時候三張表的Model都需要寫。 我們知道,一對多的關系,一般都是在多的一方做配置。具體代碼如下: 學生表 @Entity @Table(name = "T_STUDENT") @SequenceGenerator(name = "SEQ_STUDENT", sequenceName = "SEQ_STUDENT") public class Student2 implements Serializable { private static final long serialVersionUID = 2524659555729848644L; private Long id; private String name; private Date birthday; private int sex; private String address; private Set<TeacherStudent> teacherStudentList; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_STUDENT") @Column(name = "ID", nullable = false, precision = 22, scale = 0) public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column(name = "NAME") public String getName() { return name; } public void setName(String name) { this.name = name; } @Temporal(TemporalType.DATE) @Column(name = "BIRTHDAY") public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Column(name = "sex") public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } @Column(name = "address") public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @OneToMany(mappedBy="student",cascade=CascadeType.ALL) public Set<TeacherStudent> getTeacherStudentList() { return teacherStudentList; } public void setTeacherStudentList(Set<TeacherStudent> teacherStudentList) { this.teacherStudentList = teacherStudentList; } } 教師表 @Entity @Table(name = "T_TEACHER") @SequenceGenerator(name = "SEQ_TEACHER", sequenceName = "SEQ_TEACHER") public class Teacher2 implements Serializable { private static final long serialVersionUID = 2297316923535111793L; private Long id; private String name; private int sex; private Set<TeacherStudent> teacherStudentList; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_TEACHER") @Column(name = "ID", nullable = false, precision = 22, scale = 0) public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name = "sex") public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } @OneToMany(mappedBy = "teacher",cascade=CascadeType.ALL) public Set<TeacherStudent> getTeacherStudentList() { return teacherStudentList; } public void setTeacherStudentList(Set<TeacherStudent> teacherStudentList) { this.teacherStudentList = teacherStudentList; } } 中間表 @Entity @Table(name = "T_TEACHERSTUDENT") @SequenceGenerator(name = "SEQ_TEACHERSTUDENT", sequenceName = "SEQ_TEACHERSTUDENT") public class TeacherStudent implements Serializable { private Long id; private Student2 student; private Teacher2 teacher; private String note1; private String note2; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_TEACHERSTUDENT") @Column(name = "ID", nullable = false, precision = 22, scale = 0) public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column(name = "note1") public String getNote1() { return note1; } public void setNote1(String note1) { this.note1 = note1; } @Column(name = "note2") public String getNote2() { return note2; } public void setNote2(String note2) { this.note2 = note2; } @ManyToOne(cascade=CascadeType.ALL) @JoinColumn(name = "student_id", unique = true) public Student2 getStudent() { return student; } public void setStudent(Student2 student) { this.student = student; } @ManyToOne @JoinColumn(name = "teacher_id", unique = true) public Teacher2 getTeacher() { return teacher; } public void setTeacher(Teacher2 teacher) { this.teacher = teacher; } } hibernate.cfg.xml 引入對象 <mapping class="com.dvn.li.model.Student2"/> <mapping class="com.dvn.li.model.Teacher2"/> <mapping class="com.dvn.li.model.TeacherStudent"/> 測試: SessionFactory sessionFactory = null; Session session = null; try { sessionFactory = HibernateUtil.getSessionFactory(); session = sessionFactory.getCurrentSession(); session.beginTransaction(); Student2 s = new Student2(); s.setName("小豬"); Teacher2 t = new Teacher2(); t.setName("小李"); TeacherStudent ts=new TeacherStudent(); ts.setStudent(s); ts.setTeacher(t); ts.setNote1("以呀呀!!!"); session.save(s); session.save(t); session.save(ts); session.getTransaction().commit(); } catch (Exception e) { if (session != null) { session.getTransaction().rollback(); } } 測試通過!
hibernate annotation多對多中間表添加其他字段的第三種方法
本示例主要以學生(T_Student)和課程(T_Course)之間的多對多關系,中間表Score(分數),學生表和課程表是多對多關系,另外為他們的關系添加額外的字段---分數: T_Student類如下: package server.com.upc.test; import Java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.MapKey; @Entity public class T_Student { private int id; private String name; private Map<String,T_Crouse> course=new HashMap<String,T_Crouse>(); /* * 或者 * private Set<T_Crouse> course=new HashSet<T_Crouse>(); * * */ @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; } /* * 或者 * @ManyToMany @JoinTable( name="score", joinColumns=@JoinColumn(name="student_id"), inverseJoinColumns=@JoinColumn(name="course_id") ) * */ @ManyToMany @MapKey(name="id") @JoinTable( name="score", joinColumns=@JoinColumn(name="student_id"), inverseJoinColumns=@JoinColumn(name="course_id") ) public Map<String, T_Crouse> getCourse() { return course; } public void setCourse(Map<String, T_Crouse> course) { this.course = course; } } T_course類: package server.com.upc.test; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class T_Crouse { 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; } } 中間表Score也寫成實體類: package server.com.upc.test; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; @Entity @Table(name="score") public class T_Score { private int id; private int scrores; private T_Student student; private T_Crouse course; @Id @GeneratedValue public int getId() { return id; } public int getScrores() { return scrores; } public void setScrores(int scrores) { this.scrores = scrores; } public void setId(int id) { this.id = id; } @ManyToOne @JoinColumn(name="student_id") public T_Student getStudent() { return student; } public void setStudent(T_Student student) { this.student = student; } @ManyToOne @JoinColumn(name="course_id") public T_Crouse getCourse() { return course; } public void setCourse(T_Crouse course) { this.course = course; } } 注意的是中間表中的導航關系manytomany @JoinColumn(name="course_id");@JoinColumn(name="course_id")中聲明的course_id,student_id和T_student表中聲明的要一致,不然會產生其他的字段--再就是中間表的@Table(name="score")score名字和T_Student中的 @JoinTable( name="score",要一樣!!! 建立好之后就會生成中間表含有字段id,student_id,course_id,和score四個字段(然后hibernate生成的主鍵是(student_id,coure_id))雖然你在T_Score表中聲明了自己的id。。。。這是值得注意的地方!