《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進行關聯關系更容易了解和實作。是以,建議使用。