总结:Hibernate关联关系映射——七种映射的实现(更新中)
来源:互联网 发布:java用ftp上传文件 编辑:程序博客网 时间:2024/05/24 07:38
- 一对一关联
- 共享主键方式
- 唯一外键方式
- 多对一单向关联
- 一对多双向关联
- 多对多单向关联
- 多对多双向关联
一对一关联
Hibernate映射实体的一对一关联方式有共享主键方式和唯一外键方式。共享主键就是两个表的主键完全相同,保证一对一。唯一外键就是一个表的唯一外键对应另一个表的唯一主键,来保证一对一。
共享主键方式
唯一外键方式
现实中一个人住一个房间,一个房间是可以多个人住的,这就是多对一的关系,但我们限制每个房间只能住一个人,就成了一对一的关系,所以说一对一关系其实是多对一关系的一种特殊情况。
建立JAVA工程之后生成POJO类如下
可以看到生成的Person.java中没有Integer room_id
,取而代之的是Room room
package org.vo;/** * Person entity. @author MyEclipse Persistence Tools */public class Person implements java.io.Serializable { // Fields private Integer id; private Room room; private String name; // Constructors /** default constructor */ public Person() { } /** minimal constructor */ public Person(String name) { this.name = name; } /** full constructor */ public Person(Room room, String name) { this.room = room; this.name = name; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public Room getRoom() { return this.room; } public void setRoom(Room room) { this.room = room; } public String getName() { return this.name; } public void setName(String name) { this.name = name; }}
修改Room.java
package org.vo;import java.util.HashSet;import java.util.Set;/** * Room entity. @author MyEclipse Persistence Tools */public class Room implements java.io.Serializable { // Fields private Integer id; private String address; //private Set persons = new HashSet(0); private Person person; // Constructors /** default constructor */ public Room() { } /** minimal constructor */ public Room(String address) { this.address = address; } /** full constructor */ public Room(String address, Person person) { this.address = address; this.person = person; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getAddress() { return this.address; } public void setAddress(String address) { this.address = address; } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; }/* public Set getPersons() { return this.persons; } public void setPersons(Set persons) { this.persons = persons; }*/}
修改Person.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="org.vo.Person" table="Person" schema="dbo" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native" /> </id> <many-to-one name="room" column="room_id" class="org.vo.Room" cascade="all" unique="true"/> <property name="name" type="java.lang.String"> <column name="name" length="50" not-null="true" /> </property> </class></hibernate-mapping>
修改Room.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="org.vo.Room" table="Room" schema="dbo" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native" /> </id> <property name="address" type="java.lang.String"> <column name="address" length="100" not-null="true" /> </property> <one-to-one name="person" class="org.vo.Person" property-ref="room"/> </class></hibernate-mapping>
最后编写测试类Test.java:
package org.test;import org.hibernate.Session;import org.hibernate.Transaction;import org.util.HibernateSessionFactory;import org.vo.Person;import org.vo.Room;public class Test { public static void main(String[] args) { Person person = new Person(); person.setName("xp"); Room room = new Room(); room.setAddress("NJ-S1-328"); person.setRoom(room); Session session = HibernateSessionFactory.getSession(); Transaction t = session.beginTransaction(); session.save(person); t.commit(); session.close(); }}
执行后查看Person表和Room表如下
可以看到,我们为person设置了room以后,保存person,其room也会保存到数据库中
多对一单向关联
只要把一个房间只能住一个人的限制去掉,每个房间可以住多个人,每个人只能住一个房间,就构成了多对一单向关联
把Person.hbm.xml文件中的
unique="true"去掉
修改Room.java
package org.vo;import java.util.HashSet;import java.util.Set;/** * Room entity. @author MyEclipse Persistence Tools */public class Room implements java.io.Serializable { // Fields private Integer id; private String address; //private Set persons = new HashSet(0); //private Person person; // Constructors /** default constructor */ public Room() { } /** minimal constructor */ /** full constructor */ public Room(String address) { this.address = address; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getAddress() { return this.address; } public void setAddress(String address) { this.address = address; }/* public Set getPersons() { return this.persons; } public void setPersons(Set persons) { this.persons = persons; }*/}
- 把Room.hbm.xml中的
<one-to-one name="person" class="org.vo.Person" property-ref="room"/>
去掉
重新编写一下测试类
package org.test;import org.hibernate.Session;import org.hibernate.Transaction;import org.util.HibernateSessionFactory;import org.vo.Person;import org.vo.Room;public class Test { public static void main(String[] args) { Session session = HibernateSessionFactory.getSession(); Transaction t = session.beginTransaction(); Room room = new Room(); room.setAddress("NJ-S1-413"); Person person1 = new Person(); person1.setName("Jason"); person1.setRoom(room); Person person2 = new Person(); person2.setName("Lucas"); person2.setRoom(room); session.save(person1); session.save(person2); t.commit(); session.close(); }}
执行后查表
可以看出,两个person使用了相同的房间。
在这个例子中插入person对象可以同时插入room对象,而插入room对象不会对person表产生影响
一对多双向关联
在多对一双向关联中,根据Person可以看到Room,但是根据Room并不能看到Person,如果我们在Room中加入一个persons ,让Room也可以知道Person,就构成了双向一对多关联。
- 修改Room.java
package org.vo;import java.util.HashSet;import java.util.Set;/** * Room entity. @author MyEclipse Persistence Tools */public class Room implements java.io.Serializable { // Fields private Integer id; private String address; private Set persons = new HashSet(0); //private Person person; // Constructors /** default constructor */ public Room() { } /** minimal constructor */ public Room(String address) { this.address = address; } /** full constructor */ public Room(String address, Set persons) { this.address = address; this.persons = persons; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getAddress() { return this.address; } public void setAddress(String address) { this.address = address; } public Set getPersons() { return this.persons; } public void setPersons(Set persons) { this.persons = persons; }}
- 修改Room.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="org.vo.Room" table="Room" schema="dbo" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native" /> </id> <property name="address" type="java.lang.String"> <column name="address" length="100" not-null="true" /> </property> <set name="persons" inverse="false" cascade="all"> <key column="room_id"/> <one-to-many class="org.vo.Person"/> </set> </class></hibernate-mapping>
- 重新编写测试类
package org.test;import java.util.HashSet;import java.util.Set;import org.hibernate.Session;import org.hibernate.Transaction;import org.util.HibernateSessionFactory;import org.vo.Person;import org.vo.Room;public class Test { public static void main(String[] args) { Session session = HibernateSessionFactory.getSession(); Transaction t = session.beginTransaction(); Room room = new Room(); room.setAddress("NJ-S1-219"); Person person1 = new Person(); person1.setName("Paul"); Person person2 = new Person(); person2.setName("Bob"); Set<Person> persons = new HashSet<Person>(); persons.add(person1); persons.add(person2); room.setPersons(persons); session.save(room); t.commit(); session.close(); }}
执行后查表:
可以看出,我们为Room设置了Person后,保存Room,Person也被自动保存到数据库中。
多对多单向关联
学生和课程就是多对多的关系,一个学生可以选择多门课程,一门课程也可以被多个学生选择,我们按照下面的关系建立数据库
这里的stu_cour就是一张连接表,表明student和course间的关系
建立Java工程后,用反向工程生成POJO类如下
(stu_cour表不需要做反向工程)
- 修改Student.java
package org.vo;import java.util.HashSet;import java.util.Set;/** * Student entity. @author MyEclipse Persistence Tools */public class Student implements java.io.Serializable { // Fields private Integer id; private String snumber; private String sname; private Integer sage; private Set courses = new HashSet(0); // Constructors /** default constructor */ public Student() { } /** minimal constructor */ public Student(String snumber) { this.snumber = snumber; } /** full constructor */ public Student(String snumber, String sname, Integer sage, Set courses) { this.snumber = snumber; this.sname = sname; this.sage = sage; this.courses = courses; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getSnumber() { return this.snumber; } public void setSnumber(String snumber) { this.snumber = snumber; } public String getSname() { return this.sname; } public void setSname(String sname) { this.sname = sname; } public Integer getSage() { return this.sage; } public void setSage(Integer sage) { this.sage = sage; } public Set getCourses() { return courses; } public void setCourses(Set courses) { this.courses = courses; }}
- 修改
Student.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="org.vo.Student" table="student" schema="dbo" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="ID" /> <generator class="native" /> </id> <property name="snumber" type="java.lang.String"> <column name="SNUMBER" length="10" not-null="true" /> </property> <property name="sname" type="java.lang.String"> <column name="SNAME" length="10" /> </property> <property name="sage" type="java.lang.Integer"> <column name="SAGE" /> </property> <set name="courses" table="stu_cour" lazy="true" cascade="all"> <key column="SID"></key> <many-to-many class="org.vo.Course" column="CID"></many-to-many> </set> </class></hibernate-mapping>
- 编写测试类
package org.test;import java.util.HashSet;import java.util.Set;import org.hibernate.Session;import org.hibernate.Transaction;import org.util.HibernateSessionFactory;import org.vo.Course;import org.vo.Student;public class Test { public static void main(String[] args) { Course cour1= new Course(); Course cour2= new Course(); Course cour3= new Course(); cour1.setCnumber("101"); cour1.setCname("计算机网络"); cour2.setCnumber("102"); cour2.setCname("数据结构"); cour3.setCnumber("103"); cour3.setCname("数据库原理"); Set<Course> courses = new HashSet<Course>(); courses.add(cour1); courses.add(cour2); courses.add(cour3); Student stu = new Student(); stu.setSnumber("20151"); stu.setSname("张灿"); stu.setSage(19); stu.setCourses(courses); Session session = HibernateSessionFactory.getSession(); Transaction t = session.beginTransaction(); session.save(stu); t.commit(); session.close(); }}
运行后查看数据库
可以看到,为student设置courses后,保存student,student表插入了学生信息,course表插入了课程信息,连接表插入它们的关联信息。
多对多双向关联
在上个例子中,只有student可以控制course,而插入course并不会对student产生影响,我们可以为course也做几乎同样的修改,就可以变成双向关联了。
- 修改Course.java
package org.vo;import java.util.HashSet;import java.util.Set;/** * Course entity. @author MyEclipse Persistence Tools */public class Course implements java.io.Serializable { // Fields private Integer id; private String cnumber; private String cname; private Set students = new HashSet(0); // Constructors /** default constructor */ public Course() { } /** minimal constructor */ public Course(String cnumber) { this.cnumber = cnumber; } /** full constructor */ public Course(String cnumber, String cname, Set students) { this.cnumber = cnumber; this.cname = cname; this.students = students; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getCnumber() { return this.cnumber; } public void setCnumber(String cnumber) { this.cnumber = cnumber; } public String getCname() { return this.cname; } public void setCname(String cname) { this.cname = cname; } public Set getStudents() { return students; } public void setStudents(Set students) { this.students = students; }}
- 修改
Course.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="org.vo.Course" table="course" schema="dbo" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="ID" /> <generator class="native" /> </id> <property name="cnumber" type="java.lang.String"> <column name="CNUMBER" length="10" not-null="true" /> </property> <property name="cname" type="java.lang.String"> <column name="CNAME" length="20" /> </property> <set name="students" table="stu_cour" lazy="true" cascade="all"> <key column="CID"></key> <many-to-many class="org.vo.Student" column="SID"></many-to-many> </set> </class></hibernate-mapping>
- 重新编写测试类
package org.test;import java.util.HashSet;import java.util.Set;import org.hibernate.Session;import org.hibernate.Transaction;import org.util.HibernateSessionFactory;import org.vo.Course;import org.vo.Student;public class Test { public static void main(String[] args) { Student stu1 = new Student(); stu1.setSnumber("20168"); stu1.setSname("朱杰"); stu1.setSage(20); Student stu2 = new Student(); stu2.setSnumber("20156"); stu2.setSname("王猛"); stu2.setSage(20); Set students = new HashSet(); students.add(stu1); students.add(stu2); Course course=new Course(); course.setCname("算法分析"); course.setCnumber("109"); course.setStudents(students); Session session = HibernateSessionFactory.getSession(); Transaction t = session.beginTransaction(); session.save(course); t.commit(); session.close(); }}
执行后查看数据库
可以看出我们为course设置student后,保存course,也会保存student,和关联信息
参考:
[1]郑阿奇.Java EE实用教程[M].北京:电子工业出版社,2015.2:190-195
- 总结:Hibernate关联关系映射——七种映射的实现(更新中)
- Hibernate的七种映射关系之七种关联映射(一)
- Hibernate的七种映射关系之七种关联映射(二)
- Hibernate的七种映射关系之七种关联映射(二)
- Hibernate映射(二)——七种映射关系
- Hibernate(七)实现多对多关联映射关系
- Hibernate(七)实现多对多关联映射关系
- hibernate关系映射——关联映射
- Hibernate映射——一对多关联映射(七)
- Hibernate映射——一对多关联映射(七)
- Hibernate的七种映射关系之七种关联映射
- Hibernate的七种映射关系之七种关联映射
- Hibernate映射解析——七种映射关系
- Hibernate映射解析——七种映射关系
- Hibernate映射解析——七种映射关系
- Hibernate映射解析——七种映射关系
- Hibernate映射解析——七种映射关系
- Hibernate映射解析——七种映射关系
- ubuntu 1920x1080 vmware
- 女神进化论寺主人:如何用设计思维,从 0 做到 300 万粉丝?
- 软件人生感触之三 so与全局变量
- 566. Reshape the Matrix
- 进程
- 总结:Hibernate关联关系映射——七种映射的实现(更新中)
- 快手CEO宿华:在毛细血管的末梢记录变化的世界 | WISE2017新商业大会
- android如何查看手机中的db文件,查看sqlite数据库的表结构
- 华风爱科CEO冯雪:看到天气的经济价值 | WISE2017新商业大会
- 这 12 个趋势,将引爆 2018 用户体验设计潮流
- 乂学教育、朋友印象创始人栗浩洋:这轮 AI 风潮中谁会杀死 BAT? | WISE2017新商业大会
- 外媒评2017年科技滑铁卢:亚马逊Key、HomePod、Uber纷纷上榜
- Eclipse+GitHub的安装与使用教程(亲测可用)
- c/c++实现将cef的一堆dll单独放在一个文件夹,与程序exe目录区分开