您的位置:首页 > 其它

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

2016-05-02 21:09 337 查看

《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语句输出到数据库中。

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



以上,这样我们就通过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文件实现

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



将上述方法应用到我们的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进行关联关系更容易理解和实现。因此,建议使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: