欢迎来到小米的博客
希望能和您交流Java编程的知识和见解
BlogJava
首页
新随笔
联系
聚合
管理
随笔-57 评论-202 文章-17 trackbacks-0
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
;
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
>
由于在建立外键的时候就声明了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
@hibernate.id
34
generator
-
class
=
"
foreign
"
35
type
=
"
int
"
36
column
=
"
Guid
"
37
38
39
</
meta
>
40
<
generator
class
=
"
foreign
"
>
41
<
param name
=
"
property
"
>
userBasic
</
param
>
42
</
generator
>
43
</
id
>
44
45
<
property
46
name
=
"
username
"
47
type
=
"
java.lang.String
"
48
column
=
"
Username
"
49
length
=
"
128
"
50
>
51
<
meta attribute
=
"
field-description
"
>
52
@hibernate.property
53
column
=
"
Username
"
54
length
=
"
128
"
55
</
meta
>
56
</
property
>
57
<
property
58
name
=
"
gender
"
59
type
=
"
java.lang.String
"
60
column
=
"
Gender
"
61
length
=
"
1
"
62
>
63
<
meta attribute
=
"
field-description
"
>
64
@hibernate.property
65
column
=
"
Gender
"
66
length
=
"
1
"
67
</
meta
>
68
</
property
>
69
<
property
70
name
=
"
birthday
"
71
type
=
"
java.sql.Date
"
72
column
=
"
Birthday
"
73
length
=
"
19
"
74
>
75
<
meta attribute
=
"
field-description
"
>
76
@hibernate.property
77
column
=
"
Birthday
"
78
length
=
"
19
"
79
</
meta
>
80
</
property
>
81
82
<!--
Associations
-->
83
84
<!--
bi
-
directional one
-
to
-
one association to UserBasic
-->
85
<
one
-
to
-
one
86
name
=
"
userBasic
"
87
class
=
"
com.xxx.hibernate.UserBasic
"
88
constrained
=
"
true
"
89
>
90
<
meta attribute
=
"
field-description
"
>
91
@hibernate.one
-
to
-
one
92
class
=
"
com.xxx.hibernate.UserBasic
"
93
constrained
=
"
true
"
94
</
meta
>
95
</
one
-
to
-
one
>
96
97
</
class
>
98
</
hibernate
-
mapping
>
用hbm2java生成对应的对应的Java类:hbm2java *.xml --output=xxx。
Hibernate的配置文件hibernate.cfg.xml内容如下:
1
<?
xml version="1.0" encoding="utf-8"
?>
2
<!
DOCTYPE hibernate-configuration
3
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
4
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"
>
5
6
<
hibernate-configuration
>
7
<
session-factory
>
8
9
<!--
local connection properties
-->
10
<
property
name
="hibernate.connection.url"
>
jdbc:mysql://127.0.0.1/xxx?useUnicode=true
&
characterEncoding=UTF-8
&
autoReconnect=true
</
property
>
11
<
property
name
="hibernate.connection.driver_class"
>
com.mysql.jdbc.Driver
</
property
>
12
<
property
name
="hibernate.connection.username"
>
root
</
property
>
13
<
property
name
="hibernate.connection.password"
>
123456
</
property
>
14
<!--
property name="hibernate.connection.pool_size"></property
-->
15
16
<!--
dialect for MySQL
-->
17
<
property
name
="dialect"
>
net.sf.hibernate.dialect.MySQLDialect
</
property
>
18
19
<
property
name
="hibernate.show_sql"
>
true
</
property
>
20
<
property
name
="hibernate.use_outer_join"
>
true
</
property
>
21
<
property
name
="hibernate.transaction.factory_class"
>
net.sf.hibernate.transaction.JDBCTransactionFactory
</
property
>
22
23
<
mapping
resource
="com/xxx/hibernate/UserBasic.hbm.xml"
/>
24
<
mapping
resource
="com/xxx/hibernate/UserInfo.hbm.xml"
/>
25
26
</
session-factory
>
27
</
hibernate-configuration
>
JUnit的测试用例程序片断如下:
1
public
void
testInsertUser() throws Exception
{
2
UserBasic user
=
new
UserBasic();
3
user.setAccount(
"
test
"
);
4
user.setPassword(
"
123456
"
);
5
user.setEmail(
"
georgehill@21cn.com
"
);
6
7
UserInfo info
=
new
UserInfo();
8
info.setUsername(
"
George Hill
"
);
9
info.setGender(
"
M
"
);
10
info.setBirthday(
new
Date());
11
12
user.setUserInfo(info);
13
info.setUserBasic(user);
14
15
Transaction tx
=
session.beginTransaction();
16
session.save(user);
17
tx.commit();
18
}
运行测试程序,可以看到输出了两条insert语句。
posted on 2005-05-14 15:02
小米
阅读(4036)
评论(2)
编辑
收藏
所属分类:
Hibernate
评论:
#
re: Hibernate的一对一关联实例 2014-10-16 16:03 |
vds
好样的
回复
更多评论
#
re: Hibernate的一对一关联实例
2016-06-17 15:32 |
33
根据写了报错了是怎么回事
回复
更多评论
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
知识库
C++博客
博问
管理
相关文章:
《深入浅出Hibernate》读书笔记(9)——Session管理
《深入浅出Hibernate》读书笔记(8)——Hibernate分页
《深入浅出Hibernate》读书笔记(7)——回调与拦截机制
《深入浅出Hibernate》读书笔记(6)——集合类型和结果集排序
《深入浅出Hibernate》读书笔记(5)——持久层操作
《深入浅出Hibernate》读书笔记(4)——事务管理
《深入浅出Hibernate》读书笔记(3)——数据缓存
《深入浅出Hibernate》读书笔记(2)——实体对象识别
《深入浅出Hibernate》读书笔记(1)——实体对象生命周期
用HQL获取部分的实体对象属性
小米,生活在深圳,专注于Java,主要从事数据库和网页编程。现在在学习着Hibernate和Spring。喜欢游戏、音乐和台球。联系方式:georgehill@21cn.com
<
2014年10月
>
日
一
二
三
四
五
六
28
29
30
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
31
1
2
3
4
5
6
7
8
常用链接
我的随笔
我的评论
我的参与
最新评论
留言簿
(27)
给我留言
查看公开留言
查看私人留言
随笔分类
Hibernate(15)
Java(17)
Spring(1)
Struts(5)
其它(5)
数据库(2)
生活随笔(12)
随笔档案
2006年4月 (1)
2006年3月 (1)
2005年8月 (1)
2005年7月 (11)
2005年6月 (13)
2005年5月 (30)
文章分类
Eclipse(1)
Java(8)
其它(8)
文章档案
2005年7月 (1)
2005年6月 (13)
2005年5月 (3)
我的朋友们
emu的博客
Java BY
我的链接
Java Research
SUN Java技术中文社区
拯救程序员王俊
搜索
积分与排名
积分 - 232060
排名 - 246
最新评论
1. re: Hibernate的一对一关联实例
根据写了报错了是怎么回事
--33
2. re: 用java.util.Timer定时执行任务
评论内容较长,点击标题查看
--yunp
3. re: Hibernate的一对一关联实例
好样的
--vds
4. re: 如何在Struts中实现分页显示数据(1)
PageData中的集合是所有都取出,还是用多少取多少,若是前者,会拖慢系统的。
--李亚男
5. re: BMP文件格式
评论内容较长,点击标题查看
--见面
阅读排行榜
1. 用java.util.Timer定时执行任务(33717)
2. 用JFreeChart画柱状图的范例(10683)
3. 《深入浅出Hibernate》读书笔记(3)——数据缓存(6096)
4. 《深入浅出Hibernate》读书笔记(8)——Hibernate分页(5533)
5. 用ChartDirector在JSP中画统计图(5235)
评论排行榜
1. 如何在Struts中实现分页显示数据(2)(25)
2. 献出一份爱心 共同援助重病程序员王俊(22)
3. Struts的国际化完整解决方案(11)
4. 2005年6月27日,一个值得纪念的日子(9)
5. 《深入浅出Hibernate》读书笔记(1)——实体对象生命周期(9)