Hibernate中多对多的annotation的写法(中间表可以有多个字段)
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。。。。这是值得注意的地方!