总结:Hibernate关联关系映射——七种映射的实现(更新中)

一对一关联

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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值