Hibernate的一对一关联实例
Hibernate中的表的关联有一对一,一对多和多对多三种关联方式,在这篇笔记和接下来的笔记中,我将用我自己的实际例子来说明如何具体实施。
我使用的Hibernate版本是2.1.8,在Hibernate的网站2.1.6版本的中文文档中有关一对一的关联有下面一段表述:
5.1.11. 一对一
持久化对象之间一对一的关联关系是通过one-to-one元素定义的。 
<one-to-one
name="propertyName" (1)
class="ClassName" (2)
cascade="all|none|save-update|delete" (3)
constrained="true|false" (4)
outer-join="true|false|auto" (5)
property-ref="propertyNameFromAssociatedClass" (6)
access="field|property|ClassName" (7)
/>
(1) name: 属性的名字。
(2) class (可选 - 默认是通过反射得到的属性类型):被关联的类的名字。
(3) cascade(级联) (可选) 表明操作是否从父对象级联到被关联的对象。
(4) constrained(约束) (可选) 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。这个选项影响save()和delete()在级联执行时的先后顺序(也在schema export tool中被使用)。
(5) outer-join(外连接) (可选 - 默认为 自动): 当设置hibernate.use_outer_join的时候,对这个关联允许外连接抓取。
(6) property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。
(7) access (可选 - 默认是 property): Hibernate用来访问属性的策略。

有两种不同的一对一关联: 
主键关联 
惟一外键关联 
主键关联不需要额外的表字段;两行是通过这种一对一关系相关联的,那么这两行就共享同样的主关键字值。所以如果你希望两个对象通过主键一对一关联,你必须确认它们被赋予同样的标识值! 
比如说,对下面的Employee和Person进行主键一对一关联: 
<one-to-one name="person" class="Person"/>
<one-to-one name="employee" class="Employee" constrained="true"/>
现在我们必须确保PERSON和EMPLOYEE中相关的字段是相等的。我们使用一个特别的称为foreign的Hibernate标识符生成器策略: 
<class name="person" table="PERSON">
<id name="id" column="PERSON_ID">
<generator class="foreign">
<param name="property">employee</param>
</generator>
</id>

<one-to-one name="employee"
class="Employee"
constrained="true"/>
</class>
一个刚刚保存的Person实例被赋予和该Person的employee属性所指向的Employee实例同样的关键字值。 
另一种方式是一个外键和一个惟一关键字对应,上面的Employee和Person的例子,如果使这种关联方式,应该表达成: 
<many-to-one name="person" class="Person" column="PERSON_ID" unique="true"/>
如果在Person的映射加入下面几句,这种关联就是双向的: 
<one-to-one name"employee" class="Employee" property-ref="person"/>
下面是我的一个一对一主键关联的例子,使用的数据库是MySQL 4.1.11:
我有两个表:UserBasic和UserInfo,UserBasic记录的是用户的基本注册信息,UserInfo表记录的是用户的详细信息。表的结构如下:
1
CREATE TABLE IF NOT EXISTS UserBasic
2
(
3
Guid INT NOT NULL AUTO_INCREMENT,
4
Account VARCHAR(64) NOT NULL,
5
Password VARCHAR(16) NOT NULL,
6
Email VARCHAR(128) NOT NULL,
7
PRIMARY KEY (Guid)
8
) TYPE=InnoDB;
9
10
CREATE TABLE IF NOT EXISTS UserInfo
11
(
12
Guid INT NOT NULL,
13
Username VARCHAR(128),
14
Gender CHAR(1),
15
Birthday DATETIME,
16
PRIMARY KEY (Guid)
17
) TYPE=InnoDB;
18
19
ALTER TABLE UserInfo ADD CONSTRAINT UserInfoRFUserBasic FOREIGN KEY (Guid)
20
REFERENCES UserBasic (Guid) ON DELETE CASCADE ON UPDATE RESTRICT;
CREATE TABLE IF NOT EXISTS UserBasic2
(3
Guid INT NOT NULL AUTO_INCREMENT,4
Account VARCHAR(64) NOT NULL,5
Password VARCHAR(16) NOT NULL,6
Email VARCHAR(128) NOT NULL,7
PRIMARY KEY (Guid)8
) TYPE=InnoDB;9

10
CREATE TABLE IF NOT EXISTS UserInfo11
(12
Guid INT NOT NULL,13
Username VARCHAR(128),14
Gender CHAR(1),15
Birthday DATETIME,16
PRIMARY KEY (Guid)17
) TYPE=InnoDB;18

19
ALTER TABLE UserInfo ADD CONSTRAINT UserInfoRFUserBasic FOREIGN KEY (Guid) 20
REFERENCES UserBasic (Guid) ON DELETE CASCADE ON UPDATE RESTRICT;
UserInfo的主键值和UserBasic的主键值是一样的,两个表是单向的一对一关系。UserBasic为主控方,UserInfo是被动方。
用Middlegen生成的UserBasic.hbm.xml文件,修改后的内容如下:
1
<?xml version="1.0"?>
2
<!DOCTYPE hibernate-mapping PUBLIC
3
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
4
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
5
6
<hibernate-mapping>
7
<!--
8
Created by the Middlegen Hibernate plugin 2.1
9
10
http://boss.bekk.no/boss/middlegen/
11
http://www.hibernate.org/
12
-->
13
14
<class
15
name="com.xxx.hibernate.UserBasic"
16
table="UserBasic"
17
dynamic-update="true"
18
dynamic-insert="true"
19
>
20
<meta attribute="class-description" inherit="false">
21
@hibernate.class
22
table="UserBasic"
23
dynamic-update="true"
24
dynamic-insert="true"
25
</meta>
26
27
<id
28
name="guid"
29
type="int"
30
column="Guid"
31
>
32
<meta attribute="field-description">
33
@hibernate.id
34
generator-class="native"
35
type="int"
36
column="Guid"
37
38
39
</meta>
40
<generator class="native" />
41
</id>
42
43
<property
44
name="account"
45
type="java.lang.String"
46
column="Account"
47
not-null="true"
48
length="64"
49
>
50
<meta attribute="field-description">
51
@hibernate.property
52
column="Account"
53
length="64"
54
not-null="true"
55
</meta>
56
</property>
57
<property
58
name="password"
59
type="java.lang.String"
60
column="Password"
61
not-null="true"
62
length="16"
63
>
64
<meta attribute="field-description">
65
@hibernate.property
66
column="Password"
67
length="16"
68
not-null="true"
69
</meta>
70
</property>
71
<property
72
name="email"
73
type="java.lang.String"
74
column="Email"
75
not-null="true"
76
length="128"
77
>
78
<meta attribute="field-description">
79
@hibernate.property
80
column="Email"
81
length="128"
82
not-null="true"
83
</meta>
84
</property>
85
86
<!-- Associations -->
87
88
<!-- bi-directional one-to-one association to UserInfo -->
89
<one-to-one
90
name="userInfo"
91
class="com.xxx.hibernate.UserInfo"
92
cascade="save-update"
93
>
94
<meta attribute="field-description">
95
@hibernate.one-to-one
96 class="com.xxx.hibernate.UserInfo"
97
cascade="save-update"
98
</meta>
99
</one-to-one>
100
101
</class>
102
</hibernate-mapping>
<?xml version="1.0"?>2
<!DOCTYPE hibernate-mapping PUBLIC3
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"4
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >5
6
<hibernate-mapping>7
<!-- 8
Created by the Middlegen Hibernate plugin 2.19

10
http://boss.bekk.no/boss/middlegen/11
http://www.hibernate.org/12
-->13

14
<class 15
name="com.xxx.hibernate.UserBasic" 16
table="UserBasic"17
dynamic-update="true"18
dynamic-insert="true"19
>20
<meta attribute="class-description" inherit="false">21
@hibernate.class22
table="UserBasic"23
dynamic-update="true"24
dynamic-insert="true"25
</meta>26

27
<id28
name="guid"29
type="int"30
column="Guid"31
>32
<meta attribute="field-description">33
@hibernate.id34
generator-class="native"35
type="int"36
column="Guid"37

38

39
</meta>40
<generator class="native" />41
</id>42

43
<property44
name="account"45
type="java.lang.String"46
column="Account"47
not-null="true"48
length="64"49
>50
<meta attribute="field-description">51
@hibernate.property52
column="Account"53
length="64"54
not-null="true"55
</meta> 56
</property>57
<property58
name="password"59
type="java.lang.String"60
column="Password"61
not-null="true"62
length="16"63
>64
<meta attribute="field-description">65
@hibernate.property66
column="Password"67
length="16"68
not-null="true"69
</meta> 70
</property>71
<property72
name="email"73
type="java.lang.String"74
column="Email"75
not-null="true"76
length="128"77
>78
<meta attribute="field-description">79
@hibernate.property80
column="Email"81
length="128"82
not-null="true"83
</meta> 84
</property>85

86
<!-- Associations -->87
88
<!-- bi-directional one-to-one association to UserInfo -->89
<one-to-one90
name="userInfo"91
class="com.xxx.hibernate.UserInfo"92
cascade="save-update"93
>94
<meta attribute="field-description">95
@hibernate.one-to-one96 class="com.xxx.hibernate.UserInfo"
97
cascade="save-update"98
</meta>99
</one-to-one>100

101
</class>102
</hibernate-mapping>
由于在建立外键的时候就声明了ON DELETE CASCADE,所以在xml的配置文件中第97行声明为save-update。如果声明为all,那么在删除UserBasic表的数据时,会无谓的多出一条删除UserInfo的delete语句出来。
UserInfo.hbm.xml文件的内容如下:
1
<?xml version="1.0"?>
2
<!DOCTYPE hibernate-mapping PUBLIC
3
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
4
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
5
6
<hibernate-mapping>
7
<!--
8
Created by the Middlegen Hibernate plugin 2.1
9
10
http://boss.bekk.no/boss/middlegen/
11
http://www.hibernate.org/
12
-->
13
14
<class
15
name="com.xxx.hibernate.UserInfo"
16
table="UserInfo"
17
dynamic-update="true"
18
dynamic-insert="true"
19
>
20
<meta attribute="class-description" inherit="false">
21
@hibernate.class
22
table="UserInfo"
23
dynamic-update="true"
24
dynamic-insert="true"
25
</meta>
26
27
<id
28
name="guid"
29
type="int"
30
column="Guid"
31
>
32
<meta attribute="field-description">
33
<?xml version="1.0"?>2
<!DOCTYPE hibernate-mapping PUBLIC3
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"4
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >5
6
<hibernate-mapping>7
<!-- 8
Created by the Middlegen Hibernate plugin 2.19

10
http://boss.bekk.no/boss/middlegen/11
http://www.hibernate.org/12
-->13

14
<class 15
name="com.xxx.hibernate.UserInfo" 16
table="UserInfo"17
dynamic-update="true"18
dynamic-insert="true"19
>20
<meta attribute="class-description" inherit="false">21
@hibernate.class22
table="UserInfo"23
dynamic-update="true"24
dynamic-insert="true"25
</meta>26

27
<id28
name="guid"29
type="int"30
column="Guid"31
>32
<meta attribute="field-description">33
本文详细介绍Hibernate框架中一对一关联的实现方法,包括配置文件的具体参数解释及MySQL数据库表结构设计实例。
1674

被折叠的 条评论
为什么被折叠?



