Hibernate04
Hibernate基于Annotation的配置
Annotation在框架中是越来越受欢迎了,因为annotation的配置比起XML的配置来说方便了很多,不需要大量的XML来书写,方便简单了很多,只要几个annotation的配置,就可以完成我们以前需要书写的大量的XML文件。当然annotation的配置也有缺陷的,那就是annotation一般都是配置在代码中的,如果要修改的话,需要动源代码,丧失了灵活性,违背了OCP(增加开放,修改关闭)原则,但是在真实的项目开发中,我们只是动配置文件,而不修改源代码的情况实在是太少见了,所以现在annotation已经被广泛的运用到了编程中,各种框架都提供了基于annotation的配置。
下面我们来看看hibernate基于annotation的配置吧,在学之前,我们需要知道一些hibernate关于annotation的常识:
1、 hibernate中的annotation是基于JPA这个包的,如果是4.0之前的版本,hibernate的required文件夹下,没有jpa的包,需要去jpa文件夹下加入jpa的包
2、 在hibernate的3.5之前需要下载hibernate的annotation的jar包
3、 在3.5之前如果使用annotation,创建Configuration是需要使用AnnotationConfiguration()来创建。
4、 在3.5之后可以直接使用Configuration来创建(不用管哪种——annotation或者XML)
使用annotation配置
Annotation的配置使得我们的项目配置文件大大的减少,所以annotation的配置现在在各种框架中的使用越来越广泛,下面我就是用annotation来试试吧。
第一个annotation配置的hibernate项目
我们就以我们以前的user案例来配置annotation版本的hibernate项目吧。
创建User.java类,注意看annotation的配置:
package com.lzcc.hibernate.entity; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="t_user") publicclass User { privateintid; private String username; private String password; private String nickname; private Date bornDate; @Id @GeneratedValue() publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getUsername() { returnusername; } publicvoid setUsername(String username) { this.username = username; } public String getPassword() { returnpassword; } publicvoid setPassword(String password) { this.password = password; } public String getNickname() { returnnickname; } publicvoid setNickname(String nickname) { this.nickname = nickname; } @Column(name="born_date") public Date getBornDate() { returnbornDate; } publicvoid setBornDate(Date bornDate) { this.bornDate = bornDate; } public User() { } public User(int id, String username, String password, String nickname, Date bornDate) { super(); this.id = id; this.username = username; this.password = password; this.nickname = nickname; this.bornDate = bornDate; } public User(String username, String password, String nickname, Date bornDate) { super(); this.username = username; this.password = password; this.nickname = nickname; this.bornDate = bornDate; } @Override public String toString() { return"User [id=" + id + ", username=" + username + ", password=" + password + ", nickname=" + nickname + ", bornDate=" + bornDate + "]"; } } |
之后在hibernate.cfg.xml文件中加入这个实体类(注意:和配置文件相同的是也是使用mapping引入,但是不同的是使用class属性,并且不是斜杠,而是点):
<!-- 使用annotation的配置,不再使用resource,而是使用class,注意也不再是斜杠,而是点 --> <mapping class="com.lzcc.hibernate.entity.User"/> |
写单元测试类:
@Test publicvoid testAdd() { Session session = null; try { session = HibernateUtil.openSession(); session.beginTransaction(); User u = new User("laomu", "123", "老孙", DateUtil.getDate("1994-12-23")); session.save(u); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtil.closed(session); } } |
运行我们发现和使用配置文件一样,运行成功。
这就是使用annotation来配置hibernate,我们发现比起XML的配置来说,hibernate的annotation的确比较方便了许多。这个只是单表配置,下面我们来看看many-to-one的配置吧。
annotation配置many-to-one单向
还是使用我们前面的案例来讲解:
Student.java:
package com.lzcc.hibernate.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name="t_stu") publicclass Student { privateintid; private String name; private String stuNo; private ClassRoom classRoom; @Id @GeneratedValue publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } public String getStuNo() { returnstuNo; } publicvoid setStuNo(String stuNo) { this.stuNo = stuNo; } @ManyToOne @JoinColumn(name="cid") public ClassRoom getClassRoom() { returnclassRoom; } publicvoid setClassRoom(ClassRoom classRoom) { this.classRoom = classRoom; } public Student() { } public Student(int id, String name, String stuNo, ClassRoom classRoom) { super(); this.id = id; this.name = name; this.stuNo = stuNo; this.classRoom = classRoom; } public Student(String name, String stuNo, ClassRoom classRoom) { super(); this.name = name; this.stuNo = stuNo; this.classRoom = classRoom; } @Override public String toString() { return"Student [id=" + id + ", name=" + name + ", stuNo=" + stuNo + ", classRoom=" + classRoom + "]"; } } |
ClassRoom.java:
package com.lzcc.hibernate.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="t_cls_room") publicclass ClassRoom { privateintid; private String name; @Id @GeneratedValue publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } public ClassRoom() { } public ClassRoom(int id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return"ClassRoom [id=" + id + ", name=" + name + "]"; } } |
将两个实体类加入到hibernate的配置文件中:
<!-- 使用annotation的配置,不再使用resource,而是使用class,注意也不再是斜杠,而是点 --> <mapping class="com.lzcc.hibernate.entity.User"/> <mapping class="com.lzcc.hibernate.entity.Student"/> <mapping class="com.lzcc.hibernate.entity.ClassRoom"/> |
运行测试代码:
@Test publicvoid testAdd01() { Session session = null; try { session = HibernateUtil.openSession(); session.beginTransaction(); //我们先添加一方,再添加多方 ClassRoom c = new ClassRoom(); c.setName("梁山班"); session.save(c); Student stu1 = new Student("宋江", "001", c); session.save(stu1); Student stu2 = new Student("吴用", "003", c); session.save(stu2); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.getTransaction().rollback(); } } finally { HibernateUtil.closed(session); } } |
我们发现配置来说,annotation配置相当的简单,比起XML文件的配置来说要简单了很多的。
添加来说,annotation和XML配置的都一样,如果先一方,多方后添加,则符合我们的想法,会发送相应的sql数量,如果先添加多方,则会多发送几条更新外键的sql。
@Test publicvoid testAdd02() { Session session = null; try { session = HibernateUtil.openSession(); session.beginTransaction(); //如果我们先添加多的一方呢? Student stu1 = new Student(); stu1.setName("孙悟空"); stu1.setStuNo("001"); session.save(stu1); Student stu2 = new Student(); stu2.setName("猪八戒"); stu2.setStuNo("002"); session.save(stu2); ClassRoom c = new ClassRoom(); c.setName("西游班"); session.save(c); stu1.setClassRoom(c); stu2.setClassRoom(c); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.getTransaction().rollback(); } } finally { HibernateUtil.closed(session); } } |
当我们测试下面代码时发现报错了:
@Test publicvoid testAdd03() { Session session = null; try { session = HibernateUtil.openSession(); session.beginTransaction(); //我们先添加一方,再添加多方 ClassRoom c = new ClassRoom(); c.setName("红楼班"); Student stu1 = new Student("贾宝玉", "001", c); session.save(stu1); Student stu2 = new Student("林黛玉", "003", c); session.save(stu2); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.getTransaction().rollback(); } } finally { HibernateUtil.closed(session); } } |
和XML配置一样,因为我们这样需要强制关联,那么annotation的强制关联怎么写?
这样就不报错了,但是我们前面就说过,cascade我们一般是不会使用的,只有一些特殊情况才会使用,如在删除一方时,需要关联删除多方时,这些特殊才会使用,但是基本我们也不会这样使用,因为我们要删除时,需要自己控制代码的运行,那么我们一般会在业务层自己写逻辑代码来完成。
@Test publicvoid testLoad01() { Session session = null; try { session = HibernateUtil.openSession(); Student stu = (Student) session.load(Student.class, 1); System.out.println(stu.getName()); System.out.println(stu.getClassRoom().getName()); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.getTransaction().rollback(); } } finally { HibernateUtil.closed(session); } } |
运行代码,我们发现基于annotation的配置,load方法没有延迟加载,那么如果我们想要延迟加载的话,需要这样配置:
此时运行代码:
延迟加载就有了,至于到底使用不使用延迟加载,这个就要根据项目的实际情况而定了。
annotation配置many-to-one双向
双向的配置和单向很类似,只是在一方设置一个存放多方的集合。
其实hibernate的annotation配置many-to-one的单向和双向很是类似,下面我们就以上面的案例来实现双向配置。
Student.java,多方配置跟单向的一样:
package com.lzcc.hibernate.entity; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name="t_stu") publicclass Student { privateintid; private String name; private String stuNo; private ClassRoom classRoom; @Id @GeneratedValue publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } public String getStuNo() { returnstuNo; } publicvoid setStuNo(String stuNo) { this.stuNo = stuNo; } @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="cid") public ClassRoom getClassRoom() { returnclassRoom; } publicvoid setClassRoom(ClassRoom classRoom) { this.classRoom = classRoom; } public Student() { } public Student(int id, String name, String stuNo, ClassRoom classRoom) { super(); this.id = id; this.name = name; this.stuNo = stuNo; this.classRoom = classRoom; } public Student(String name, String stuNo, ClassRoom classRoom) { super(); this.name = name; this.stuNo = stuNo; this.classRoom = classRoom; } @Override public String toString() { return"Student [id=" + id + ", name=" + name + ", stuNo=" + stuNo + ", classRoom=" + classRoom + "]"; } } |
ClassRoom.java:
package com.lzcc.hibernate.entity; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name="t_cls_room") public class ClassRoom { private int id; private String name; private Set<Student> students; @OneToMany(mappedBy="classRoom") public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } @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; } public ClassRoom() { } public ClassRoom(int id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return "ClassRoom [id=" + id + ", name=" + name + "]"; } } |
测试代码:
@Test publicvoid testAdd01() { Session session = null; try { session = HibernateUtil.openSession(); session.beginTransaction(); Student stu1 = new Student(); stu1.setName("曹操"); stu1.setStuNo("001"); session.save(stu1); Student stu2 = new Student(); stu2.setName("刘备"); stu2.setStuNo("002"); session.save(stu2); ClassRoom c = new ClassRoom(); c.setName("三国班"); Set<Student> stus = new HashSet<Student>(); stus.add(stu1); stus.add(stu2); c.setStudents(stus); session.save(c); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.getTransaction().rollback(); } } finally { HibernateUtil.closed(session); } } |
运行结果如下:
测试load方法:
@Test publicvoid testLoad() { Session session = null; try { session = HibernateUtil.openSession(); ClassRoom c = (ClassRoom) session.load(ClassRoom.class, 5); System.out.println(c.getName()); System.out.println(c.getStudents().size()); Student s = (Student) session.load(Student.class, 10); System.out.println(s.getName()); System.out.println(s.getClassRoom().getName()); } catch (Exception e) { e.printStackTrace(); } finally { HibernateUtil.closed(session); } } |
我们发现annotation的配置延迟加载默认不存在了,因为annotation的配置出现的比较晚,这时候hibernate的开发团队发现延迟加载在分层体系中的确不再有那么好的优势,而且因为延迟加载的问题导致hibernate的异常难用,所以默认就不在提供延迟加载了,当然如果想使用延迟加载也行,在many-to-one的annotation中加入就行了:
@ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="cid") public ClassRoom getClassRoom() { returnclassRoom; } |
除此之外,我们发现了一个问题,如果我们想查询集合或者对应关系的数量时,还是没有使用count(*)这种计数函数,如果我们想要使用的话(当然,如果延迟加载不使用,不建议使用,因为没有延迟加载只会发送一条sql,而加上配置,则会单独的发一条sql完成),可以配置如下:
@OneToMany(mappedBy="classRoom") @LazyCollection(LazyCollectionOption.EXTRA) public Set<Student> getStudents() { returnstudents; } |
注意在one-to-many中加入LazyCollection的annotation中加入extar值,在运行代码,我们发现的确计数使用了count函数:
但是我们也看出了,多发送了一条sql,所以annotation配置hibernate的话,如果不手动开启延迟加载,不建议开启这个配置。
annotation配置one-to-one双向
还是以person和IDCard为例:
Persion.java:
package com.lzcc.hibernate.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table(name = "t_person") publicclass Person { privateintid; private String name; private IDCard idCard; @Id @GeneratedValue publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } @OneToOne(mappedBy = "person") public IDCard getIdCard() { returnidCard; } publicvoid setIdCard(IDCard idCard) { this.idCard = idCard; } public Person() { } public Person(int id, String name, IDCard idCard) { super(); this.id = id; this.name = name; this.idCard = idCard; } public Person(String name, IDCard idCard) { super(); this.name = name; this.idCard = idCard; } public Person(String name) { super(); this.name = name; } @Override public String toString() { return"Person [id=" + id + ", name=" + name + ", idCard=" + idCard + "]"; } } |
IDCard.java:
package com.lzcc.hibernate.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table(name="t_id_card") publicclass IDCard { privateintid; private String no; private Person person; @OneToOne @JoinColumn(name="pid") public Person getPerson() { returnperson; } publicvoid setPerson(Person person) { this.person = person; } @Id @GeneratedValue publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getNo() { returnno; } publicvoid setNo(String no) { this.no = no; } public IDCard() { } public IDCard(String no) { super(); this.no = no; } public IDCard(int id, String no) { super(); this.id = id; this.no = no; } @Override public String toString() { return"IDCard [id=" + id + ", no=" + no + "]"; } } |
此时运行代码:
@Test publicvoid testAdd01() { Session session = null; try { session = HibernateUtil.openSession(); session.beginTransaction(); IDCard card = new IDCard("110120"); session.save(card); //将IDCard设置到用户属性中,表示这个一个一对一的关联 //表示张三的身份证号码为:110120 Person p = new Person("张三", card); session.save(p); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.getTransaction().rollback(); } } finally { HibernateUtil.closed(session); } } |
代码成功运行,但是我们发现外键没有被关联插入,这是因为annotation的配置中我们明确规定了不由Person端维护关系,有IDCard端的person字段维护关系,那么我们如果要插入数据,必须先有Person,这样IDCard插入数据时才有person字段的id完成外键关联。所以,注意:一对一的annotation配置后,一定要先插入不维护关系的一方。
那么我们先插入不维护关系的一端:
@Test publicvoid testAdd02() { Session session = null; try { session = HibernateUtil.openSession(); session.beginTransaction(); Person p = new Person("张三 "); session.save(p); IDCard card = new IDCard("110120"); card.setPerson(p); session.save(card); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.getTransaction().rollback(); } } finally { HibernateUtil.closed(session); } } |
成功的完成了插入。
annotation配置many-to-many
在hibernate中many-to-many这种配置我们不会使用,我们前面就说过,many-to-many我们会分解为两个many-to-one来配置,下面的代码紧紧供参考。
User.java:
package com.lzcc.hibernate.entity; import java.util.Date; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.Table; @Entity @Table(name="t_user") public class User { private int id; private String username; private String password; private String nickname; private Date bornDate; private Set<Role> roles; @ManyToMany(mappedBy="users") public Set<Role> getRoles() { return roles; } public void setRoles(Set<Role> roles) { this.roles = roles; } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public Date getBornDate() { return bornDate; } public void setBornDate(Date bornDate) { this.bornDate = bornDate; } public User() { } public User(int id, String username, String password, String nickname, Date bornDate) { super(); this.id = id; this.username = username; this.password = password; this.nickname = nickname; this.bornDate = bornDate; } public User(String username, String password, String nickname, Date bornDate) { super(); this.username = username; this.password = password; this.nickname = nickname; this.bornDate = bornDate; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + ", nickname=" + nickname + ", bornDate=" + bornDate + "]"; } } |
Role.java:
package com.lzcc.hibernate.entity; 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.Table; @Entity @Table(name="t_role") public class Role { private int id; private String name; private Set<User> users; @ManyToMany @JoinTable(name="t_user_role",joinColumns={@JoinColumn(name="rid")}, inverseJoinColumns={@JoinColumn(name="uid")}) public Set<User> getUsers() { return users; } public void setUsers(Set<User> users) { this.users = users; } @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; } public Role() { } public Role(String name) { this.name = name; } public Role(int id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return "Role [id=" + id + ", name=" + name + "]"; } } |
这就是多对多的配置,但是不建议使用它,我们多对多都是由两个一对多来完成,下面我来看看吧。
annotation配置many-to-many变种
还是以前面的案例来说
Student.java:
package com.lzcc.hibernate.entity; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "stu") publicclass Student { privateintid; private String name; private String stuNo; private Set<StudentCourse> tcs; @OneToMany(mappedBy="stu") public Set<StudentCourse> getTcs() { returntcs; } publicvoid setTcs(Set<StudentCourse> tcs) { this.tcs = tcs; } @Id @GeneratedValue publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } public String getStuNo() { returnstuNo; } publicvoid setStuNo(String stuNo) { this.stuNo = stuNo; } public Student() { } public Student(int id, String name, String stuNo) { this.id = id; this.name = name; this.stuNo = stuNo; } public Student(String name, String stuNo) { this.name = name; this.stuNo = stuNo; } @Override public String toString() { return"Student [id=" + id + ", name=" + name + ", stuNo=" + stuNo + "]"; } } |
Course.java:
package com.lzcc.hibernate.entity; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name="t_course") publicclass Course { privateintid; private String name; private Set<StudentCourse> tcs; @OneToMany(mappedBy="course") public Set<StudentCourse> getTcs() { returntcs; } publicvoid setTcs(Set<StudentCourse> tcs) { this.tcs = tcs; } @Id @GeneratedValue publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } public Course() { } public Course(int id, String name) { this.id = id; this.name = name; } public Course(String name) { this.name = name; } } |
TeacherCourse.java:
package com.lzcc.hibernate.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name="t_stu_course") publicclass StudentCourse { privateintid; privatedoublescore; private Student stu; private Course course; @Id @GeneratedValue publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } publicdouble getScore() { returnscore; } publicvoid setScore(double score) { this.score = score; } @ManyToOne @JoinColumn(name="sid") public Student getStu() { returnstu; } publicvoid setStu(Student stu) { this.stu = stu; } @ManyToOne @JoinColumn(name="cid") public Course getCourse() { returncourse; } publicvoid setCourse(Course course) { this.course = course; } public StudentCourse() { } public StudentCourse(int id, double score, Student stu, Course course) { super(); this.id = id; this.score = score; this.stu = stu; this.course = course; } } |
运行测试代码:
@Test publicvoid testAdd01() { Session session = null; try { session = HibernateUtil.openSession(); session.beginTransaction(); Student s1 = new Student(); s1.setName("刘建宏"); s1.setStuNo("001"); session.save(s1); Student s2 = new Student(); s2.setName("刘帅哥"); s2.setStuNo("002"); session.save(s2); Course c1 = new Course(); c1.setName("Java in Action"); session.save(c1); Course c2 = new Course(); c2.setName("PHP in Action"); session.save(c2); StudentCourse tc = new StudentCourse(); tc.setScore(88); tc.setStu(s1); tc.setCourse(c1); session.save(tc); tc = new StudentCourse(); tc.setScore(99); tc.setStu(s1); tc.setCourse(c2); session.save(tc); tc = new StudentCourse(); tc.setScore(100); tc.setStu(s2); tc.setCourse(c2); session.save(tc); tc = new StudentCourse(); tc.setScore(60); tc.setStu(s2); tc.setCourse(c1); session.save(tc); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.getTransaction().rollback(); } } finally { HibernateUtil.closed(session); } } |
我们发现结果完全一样,而且在关系表中我们可以加入一些其他的字段,这样才是我们做多对多关联的,我们在使用hibernate的时候,会将多对多分解为两个多对一来完成。
总结
Hibernate引入annotation的时间比较晚,所以annotation的配置相对来说比较好用点,因为hibernate将延迟加载等问题都屏蔽掉了(如果想使用,可以配置),所以在将来的项目中,建议如下:
1、 如果是小型项目,建议使用annotation的配置,简单方便
2、 如果是大型项目(百万行代码量及以上),建议使用hibernate