当前位置:文档之家› Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结

Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结

Hibernate(6)——一对多和多对多关联关系映射(xml和注解)总结涉及的知识点总结如下:∙One to Many 映射关系o多对一单向外键关联(XML/Annotation)o一对多单向外键关联(XML/Annotation)o懒加载和积极加载o一对多双向外键关联(XML/Annotation)∙Many to Many 映射关系o多对多单向外键关联(XML/Annotation)o多对多双向外键关联(XML/Annotation)o set的inverse元素详解∙问题小结∙关联关系的优缺点多对一单向外键关联关系注意多对一关联是多方持有一方的引用。

看一个例子,去淘宝购物,那么一个淘宝用户可以对应多个购物订单,如图所示:多的一方是Orders,持有一方的引用,也就是Users,而在Users中无需作任何定义,从订单到用户的关系是单向多对一关联。

对应数据库就是:还有比如说学生和班级的关系,多个学生可以属于同一个班级,这就是从学生到班级也是典型的单向多对一关系,看代码实现:基于注解的多对一单向外键关联:单向多对一关联中,多方需要持有一方的引用,那么多方(学生类)需要额外配置,需要对持有的一方引用使用注解@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER),设置为级联操作和饥渴的抓取策略,@JoinColumn(name="cid"),而一方(教室类)无需做任何多方的定义。

注意;多方必须保留一个不带参数的构造器!importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.Id;//班级类,在多对一关系中属于一的方,不持有其他多余的配置,反而是被多方持有@Entitypublic class ClassRoom {private intcid;//班级编号private String cname;//班级名称// 自动增长的主键@Id@GeneratedValuepublicintgetCid() {returncid;}public void setCid(intcid) {this.cid = cid;}public String getCname() {returncname;}public void setCname(String cname) {ame = cname;}}View Code一方——班级类无需做多余的定义,下面是多方——学生实体和配置:importjavax.persistence.CascadeType;importjavax.persistence.Entity;importjavax.persistence.FetchType;importjavax.persistence.GeneratedValue;importjavax.persistence.Id;importjavax.persistence.JoinColumn;importjavax.persistence.ManyToOne;//学生实体类,属于多对一的多方,持有班级(一方)的引用@Entitypublic class Students {private intsid; //编号private String sname; //姓名private ClassRoom classroom;//学生班级//注意:多方一定要显式的定义不带参数的构造方法public Students() {}public Students(String sname){this.sname = sname;}// 多方使用注解:@ManyToOne// fetch=FetchType.EAGER,急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。

// 全部级联操作,referencedColumnName显式设置数据库字段名cid,不写默认就是和name一样的。

@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER)@JoinColumn(name="cid",referencedColumnName="cid") publicClassRoomgetClassroom() {return classroom;}public void setClassroom(ClassRoom classroom) {this.classroom = classroom;}// 自动增长主键@Id@GeneratedValuepublicintgetSid() {returnsid;}public void setSid(intsid) {this.sid = sid;}public String getSname() {returnsname;}public void setSname(String sname) {this.sname = sname;}}View Code下面测试:先生成数据库脚本,再进行学生对象的插入public class TestStudentsByAnno {private static SessionFactorysessionFactory;@Beforepublic void setUp() throws Exception {System.out.println("setUp()...");sessionFactory = newAnnotationConfiguration().configure().buildSessionFactory(); }@Afterpublic void tearDown() throws Exception {System.out.println("tearDown()...");sessionFactory.close();}@Testpublic void testSave() {Session session = sessionFactory.getCurrentSession(); Transaction tx = session.beginTransaction();try {ClassRoom c = new ClassRoom();c.setCname("computer001");Students s = new Students("zhangsan");s.setClassroom(c);session.save(s);mit();} catch(Exception ex) {ex.printStackTrace();tx.rollback();}}@Test@Ignorepublic void testSchemaExport() {SchemaExport se = new SchemaExport(newAnnotationConfiguration().configure());se.create(true, true);}}View Code反向创建表的数据库脚本如下:create table ClassRoom (cid integer not null auto_increment, cnamevarchar(255), primary key (cid))create table Students (sid integer not null auto_increment, snamevarchar(255), cid integer, primary key (sid))插入一个学生对象,会自动生成如下语句:ClassRoom c = new ClassRoom();c.setCname("computer001");Students s = new Students("zhangsan");s.setClassroom(c);session.save(s);mit();View CodeHibernate: insert into ClassRoom (cname) values (?)Hibernate: insert into Students (cid, sname) values (?, ?)插入成功:基于xml配置实现多对一单向外键关联<hibernate-mapping><class name="net.nw.vo.fk.mto.ClassRoom" table="classroom"><id name="cid" column="cid" type="int"><generator class="native"/></id><property name="cname" column="cname" type="string"/></class></hibernate-mapping>View Code一方(教室类)无需做任何多方的定义。

只需要维护好自己的属性配置即可。

而多方只需要加上<many-to-one name="" column=“"/>就ok。

<hibernate-mapping><class name="net.nw.vo.fk.mto.Students" table="students"><id name="sid" column="sid" type="int"><generator class="native"/></id><property name="sname" column="sname" type="string"/><many-to-one name="classroom" column="cid"/></class></hibernate-mapping>View Codehibernate.cfg.xml里加上<mapping resource="net/nw/vo/fk/mto/ClassRoom.hbm.xml" /><mapping resource="net/nw/vo/fk/mto/Students.hbm.xml" />View Code注意:如果没有设置级联ALL,那么需要在保存的时候先保存班级,在保存学生,否则出错: object references an unsaved transient instance - save the transient instance before flushing:ClassRoomclassRoom = new ClassRoom();classRoom.setCname("CS");Students students = new Students("111");students.setClassroom(classRoom);session.save(classRoom);session.save(students);mit();View Code小结:使用<many-to-one>元素进行多对一关联关系配置,name属性指定类的属性名,column 属性指定库表字段名,class属性指定类属性类型(加上姓,即包名),not-null属性指定属性是否允许为空,cascade属性指定是否级联保存和更新:save-update、delete、all、none。

相关主题