《Hibernate学习笔记六》一对一关联关系详解

《Hibernate学习笔记六》一对一关联关系详解

从今天开始,就要开始学习关联关系了,其中关联关系,分为如下几种:

1、一对一关联关系

2、一对多关联关系

3、多对一关联 关系

4、多对多关联关系

总的来说,虽然有如上几种关联方式,但是我们可以理解它只是1中关联方式,就 多对多关联,这是因为其他的关联方式都可以理解为此关联方式的一种特殊方式。

其中,上面提到的关联关系,都存在单向和双向的关联关系。

这篇博文主要介绍下一对一关联关系。

一对一外键关联关系包括:

1、一对一单向外键关联关系的Annotation实现

2、一对一单向外键关联关系的xml实现

3、一对一双向外键关联关系的Annotation实现

4、一对一双向外键关联关系的xml实现

与外键相对应的还有主键关联。

一对一关联

我们生活中有很多一对一关联的例子,例如:”一夫一妻制”就是一对一的关联关系。一个学生有一个身份证也是一个一对一的关联关系。

一对一单向外键关联关系Annotation实现

一对一关联使用注解@OneToOne来进行修饰。

下面就以:”一夫一妻制”这个例子来进行分析。

Wife实体类

@Entity
    public class Wife {
    private int id;
    private String name;
    @Id
    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;
    }   
    }

Husband实体类

Huaband实体类中有一个Wife类的引用wife,并在getWife方法上添加了注解@OneToOne,如果我们想指定外键的名字,则通过注解@JoinColumn(name=”wifeId”)来指定,其中wifeId就是我们这个例子中指定的名字。

Husband实体类的具体代码如下:

@Entity
    public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    @OneToOne
    @JoinColumn(name="wifeId") //指定外键的名字为wifeId
    public Wife getWife() {
        return wife;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }


    }

hibernate.cfg.xml文件内容不再贴出,与前几篇博文的内容类似。

测试代码如下:

public class TeacherTest {
    @Test
    public void testSchema(){
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
        Metadata metadata = new MetadataSources(serviceRegistry).buildMetadata();
        SchemaExport schemaExport = new SchemaExport();
        schemaExport.create(EnumSet.of(TargetType.DATABASE), metadata);
    }

    }

SchemaExport类主要用于将SQL语句输出到数据库中。

在控制台我们会看到如下的主要输出信息,其中包括两条建表语句,一条插入外键的语句。

《Hibernate学习笔记六》一对一关联关系详解_第1张图片

以上,这样我们就通过Annotation建立了Husband和Wife一对一单向外键关联关系。

一对一单向外键关联关系XXX.hbm.xml的实现

现在换一个例子,以一个学生有一个身份证这样一个一对一的关联关系来举例分析。

Student类

package com.hibernate.model;

    public class Student {
    private int id;
    private String name;
    // id 、num、 student的getter和setter方法省略
    }

IdCard类

public class IdCard {
    private int id;
    private String num;
    private Student student;

    // id 、num、 student的getter和setter方法省略
    }

IdCard.hbm.xml文件内容如下:

<?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.hibernate.model">
    <class name="IdCard" table="idcard" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="num" column="num"/>
        <!-- 一对一的关联在xml文件中用many-to-one 和unique="true"联合来进行限制 -->
        <many-to-one name="student" column="studentId" unique="true"></many-to-one>      
    </class>
    </hibernate-mapping>

上面的代码中:一对一的关联关系在如下的代码中指定:

<many-to-one name="student" column="studentId" unique="true"></many-to-one>

Student.hbm.xml文件内容如下:

<?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.hibernate.model">
    <class name="Student" table="student" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>     
    </class>
    </hibernate-mapping>

这样我们就将Student和IdCard通过外键建立了一对一的关联。

测试文件与第一个例子的测试文件一样,这里不再贴出。

一对一双向外键关联Annotation实现

Student类
类中有一个Wife的引用wife。

@Entity
    public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    @OneToOne
    @JoinColumn(name="wifeId") //指定外键的名字为wifeId
    public Wife getWife() {
        return wife;
    }
    //name属性的get方法和所有属性的set方法均省略。

    }

Wife实体类

@Entity
    public class Wife {
    private int id;
    private String name;
    private Husband husband;
    @OneToOne(mappedBy="wife") //这里的意思为:外键的关联是在Husband的wife对象上面来做,即Husband是主导
    public Husband getHusband() {
        return husband;
    }
    public void setHusband(Husband husband) {
        this.husband = husband;
    }
    @Id
    public int getId() {
        return id;
    }
    //name属性的get方法和所有属性的set方法均省略。
    }

Wife类中也有一个Husband类的引用,并且需要在getHusband()方法前用@OneToOne(mappedBy=”wife”)进行注解。如果只用@OneToOne而不使用参数的注解,则会为表Husband和Wife都会建立一个外键的关联,有冗余。

最好的方法:凡是双向关联中,必须要设置@OneToOne(mappedBy=”XXX”)。

一对一双向外键关联XXX.hbm.xml文件实现

即Student类和IdCard类中均有对方的一个引用,且在IdCard.hbm.xml文件中的内容与一对一的内容不变,如下:

<?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.hibernate.model">
    <class name="IdCard" table="idcard" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="num" column="num"/>
        <!-- 一对一的关联在xml文件中用many-to-one 和unique="true"联合来进行限制 -->
        <many-to-one name="student" column="studentId" unique="true"></many-to-one>

    </class>
    </hibernate-mapping>

而在Student.hbm.xml文件中的内容,有一点变化,
加上了

<one-to-one name="idCard" class="IdCard" property-ref="student"/> 

完整内容如下:

<?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.hibernate.model">
    <class name="Student" table="student" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>  
        <!--property-ref的参数是本类所关联的类IdCard类中的Student的引用 -->
        <one-to-one name="idCard" class="IdCard" property-ref="student"/>    
    </class>
    </hibernate-mapping>

注意:在数据库中,单向和双向是没有区别的,但是,在实体类中的对应关系是有区别的。

一对一主键关联

在外键关联中,例如,会在Husband表中生成一个wifeId的字段作为外键,而主键关联则不会生成其它任意的字段。

一对一单向主键关联Annotation实现

用如下的注解来实现:

@PrimaryKeyJoinColumn //用此注解表示主键关联

@Entity
    public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    @OneToOne
    //@JoinColumn(name="wifeId") //指定外键的名字为wifeId
    @PrimaryKeyJoinColumn  //用此注解表示主键关联
    public Wife getWife() {
        return wife;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }

    //一些属性的getter/setter方法 省略
    }

一对一单向主键关联xml文件实现

在文档中,给出的方法截图如下:

《Hibernate学习笔记六》一对一关联关系详解_第2张图片

将上述方法应用到我们的Student类和IdCard类中,如下:

Student类

public class Student {
    private int id;
    private String name;    
    //...get、set方法

    }

IdCard类

public class IdCard {
    private int id;
    private String num;
    private Student student;
    //...get、set方法
    }

IdCard.hbm.xml文件内容如下

注意:此时的id生成策略。

<?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.hibernate.model">
    <class name="IdCard" table="idcard" >
        <id name="id" column="id">
            <generator class="foreign">
                <param name="property">student</param>
            </generator>
        </id>
        <property name="num" column="num"/>
        <!-- -->
        <one-to-one name="student" class="Student" constrained="true"></one-to-one>                 
    </class>
    </hibernate-mapping>

Student.hbm.xml文件内容如下

<?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.hibernate.model">
    <class name="Student" table="student" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>       
    </class>
    </hibernate-mapping>

测试结果如下:

关于主键关联这里就不再进行过多的介绍,这是由于在实际项目中,一对一关联关系并不太多,即使出现,我们一般也是采用一对一的外键进行关联。

小结

由于使用Annotation比使用xml进行关联关系更容易理解和实现。因此,建议使用。

你可能感兴趣的:(Hibernate,一对一,关联关系)