欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-04-16 08:52:01
...

《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;
    }   
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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;
    }


    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

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);
    }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

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

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

以上,这样我们就通过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方法省略
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

IdCard类

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

    // id 、num、 student的getter和setter方法省略
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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

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

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这样我们就将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方法均省略。

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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方法均省略。
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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

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

完整内容如下:

<?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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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

一对一主键关联

在外键关联中,例如,会在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方法  省略
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

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

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

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

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

Student类

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

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

IdCard类

public class IdCard {
    private int id;
    private String num;
    private Student student;
    //...get、set方法
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

测试结果如下:

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

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

小结

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


from: http://blog.csdn.net/u010412719/article/details/51298343

相关标签: hibernate