总结: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

阅读全文
0 0
原创粉丝点击