博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hibernate系列(四)一对一关联关系
阅读量:7102 次
发布时间:2019-06-28

本文共 5055 字,大约阅读时间需要 16 分钟。

以Person类和IDCard类为例,这里仅仅说一种一对一关联关系,即Person类拥有IDCard,但是IDCard不含Person类,数据库库的表如下:
 

1
2
3
4
5
6
CREATE
TABLE
`hibernate`.`person` (
  
`id`
INT
NOT
NULL
AUTO_INCREMENT,
  
`
name
`
VARCHAR
(45)
NULL
,
  
`age`
INT
NULL
,
  
`idcard_id`
INT
NULL
,
  
PRIMARY
KEY
(`id`));

1
2
3
4
5
CREATE
TABLE
`hibernate`.`idcard` (
  
`id`
INT
NOT
NULL
AUTO_INCREMENT,
  
`number`
INT
NULL
,
  
`content`
VARCHAR
(45)
NULL
,
  
PRIMARY
KEY
(`id`));

Person类如下:
 

1
2
3
4
5
6
7
8
public
class
Person {
 
    
private
Long id;
    
private
String name;
    
private
Long age;
    
private
IDCard idCard;
//省略get、set方法
}

Person类对应的Person.hbm.xml映射文件为:
 

1
2
3
4
5
6
7
8
9
10
<
hibernate-mapping
>
    
<
class
name
=
"com.ligang.domain.Person"
table
=
"person"
>
        
<
id
name
=
"id"
column
=
"id"
type
=
"long"
>
            
<
generator
class
=
"identity"
/>
        
</
id
>
        
<
property
name
=
"name"
column
=
"name"
type
=
"string"
/>
        
<
property
name
=
"age"
column
=
"age"
type
=
"long"
/>
        
<
many-to-one
name
=
"idCard"
class
=
"com.ligang.domain.IDCard"
column
=
"idcard_id"
cascade
=
"save-update"
></
many-to-one
>
    
</
class
>
</
hibernate-mapping
>

虽然是一对一但是,这种形式的一对一就是多对一的特例,所以仍然使用<many-to-one>的标签,其中的name指的是Person类的idCard属性,column指的是person表中的字段名为idcard_id,class指的是将IDCard类对应的表的主键的值作为idcard_id的值。cascade字段表示保存Person类时级联的保存IDCard类。 
下面看下IDCard类:
 

1
2
3
4
5
6
7
public
class
IDCard {
 
    
private
Long id;
    
private
Long number;
    
private
String content;
//省略get、set方法
}

IDCard类对应的IDCard.hbm.xml映射文件为:
 

1
2
3
4
5
6
7
8
9
<
hibernate-mapping
>
    
<
class
name
=
"com.ligang.domain.IDCard"
table
=
"idcard"
>
        
<
id
name
=
"id"
column
=
"id"
type
=
"long"
>
            
<
generator
class
=
"identity"
/>
        
</
id
>
        
<
property
name
=
"number"
column
=
"number"
type
=
"long"
/>
        
<
property
name
=
"content"
column
=
"content"
type
=
"string"
/>
    
</
class
>
</
hibernate-mapping
>

然后就是测试增添方法:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
    
public
void
addPerson(){
        
Session session=hibernateDao.getSession();
        
Transaction tx=session.beginTransaction();
         
        
Person p=
new
Person();
        
p.setName(
"张三"
);
        
p.setAge(122L);
         
        
IDCard idCard=
new
IDCard();
        
idCard.setNumber(123445L);
        
idCard.setContent(
"你是一个人"
);
         
        
p.setIdCard(idCard);
         
        
session.save(p);
         
        
tx.commit();
        
session.close();
    
}

此时就会先保存IDCard对象,然后获取其主键并赋值给person表的idcard_id字段,然后增添Person对象。如下sql:
 

1
2
Hibernate:
insert
into
hibernate.idcard (number, content)
values
(?, ?)
Hibernate:
insert
into
hibernate.person (
name
, age, idcard_id)
values
(?, ?, ?)

更新如下:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
    
public
void
updatePerson(){
        
Session session=hibernateDao.getSession();
        
Transaction tx=session.beginTransaction();
         
        
Person p=(Person) session.get(Person.
class
,6L);
        
p.setName(
"张三"
);
        
p.setAge(122L);
         
        
IDCard idCard=
new
IDCard();
        
idCard.setNumber(123445L);
        
idCard.setContent(
"你是一个人"
);
         
        
p.setIdCard(idCard);
         
        
session.save(p);
         
        
tx.commit();
        
session.close();
    
}

此时的sql如下:
 

1
2
3
Hibernate:
select
person0_.id
as
id1_3_0_, person0_.
name
as
name2_3_0_, person0_.age
as
age3_3_0_, person0_.idcard_id
as
idcard_i4_3_0_
from
hibernate.person person0_
where
person0_.id=?
Hibernate:
insert
into
hibernate.idcard (number, content)
values
(?, ?)
Hibernate:
update
hibernate.person
set
name
=?, age=?, idcard_id=?
where
id=?

此时并没有删除原有的IDCard,只是根据Person再也找不到它了。目前我还不知道怎么设置来删除无用的IDCard。 
获取:由Person的主键获取IDCard比较容易,但是如果想从IDCard主键获取Person呢? 
首先更改IDCard类,添加person属性:
 

1
2
3
4
5
6
7
8
public
class
IDCard {
 
    
private
Long id;
    
private
Long number;
    
private
String content;
    
private
Person person;
//略get、set方法
}

然后更改上述的IDCard.hbm.xml映射文件如下:
 

1
2
3
4
5
6
7
8
9
10
<
hibernate-mapping
>
    
<
class
name
=
"com.ligang.domain.IDCard"
table
=
"idcard"
>
        
<
id
name
=
"id"
column
=
"id"
type
=
"long"
>
            
<
generator
class
=
"identity"
/>
        
</
id
>
        
<
property
name
=
"number"
column
=
"number"
type
=
"long"
/>
        
<
property
name
=
"content"
column
=
"content"
type
=
"string"
/>
        
<
one-to-one
name
=
"person"
property-ref
=
"idCard"
></
one-to-one
>
    
</
class
>
</
hibernate-mapping
>

添加了<one-to-one>标签,同时使用了property-ref属性,看下查询再解释:
 

1
2
3
4
5
6
7
8
9
10
11
@Test
    
public
void
getPerson(){
        
Session session=hibernateDao.getSession();
        
Transaction tx=session.beginTransaction();
         
        
IDCard idCard=(IDCard) session.get(IDCard.
class
,2L);
        
System.out.println(idCard.getPerson().getName());
         
        
tx.commit();
        
session.close();
    
}

查询的sql如下:
 

1
2
Hibernate:
select
idcard0_.id
as
id1_1_0_, idcard0_.number
as
number2_1_0_, idcard0_.content
as
content3_1_0_, person1_.id
as
id1_3_1_, person1_.
name
as
name2_3_1_, person1_.age
as
age3_3_1_, person1_.idcard_id
as
idcard_i4_3_1_
from
hibernate.idcard idcard0_
left
outer
join
hibernate.person person1_
on
idcard0_.id=person1_.idcard_id
where
idcard0_.id=?
张三

将Person查出来了,然后看下他是怎么查的,看下IDCard的<one-to-one name="person" property-ref="idCard">,name指的是IDCard的person属性,而property-ref指向了另一个类的属性,这里就是Person类的idCard属性,要想查出Person总要告诉hibernate idcard表的哪个字段和person表的哪个字段相连接吧,这里的property-ref="idCard",即指定了要和Person类的idCard属性所对应的字段相连接,默认是采用主键来和该字段相连接的,我不知道能否指定。即idcard表的主键id和Person类的idCard属性对应的字段idcard_id相连接,来查询Person,看sql语句:hibernate.idcard idcard0_ left outer join hibernate.person person1_ on idcard0_.id=person1_.idcard_id 
上述一对一的关联关系是通过外键来连接,他们也可以使用相同的主键实现一对一。这里不再讲述。 

转载地址:http://ywyhl.baihongyu.com/

你可能感兴趣的文章
编写shell脚本处理test文件
查看>>
搭建网络ghost服务器
查看>>
MySQL集群搭建步骤详解
查看>>
什么是活动目录
查看>>
spark install
查看>>
Postgres Hooks
查看>>
如何写好一篇技术博客?
查看>>
SQLserver将一张表a的数据插入另一张表b
查看>>
HTTP状态码详解
查看>>
META元标记详解
查看>>
Linux上Aapache 启动不了,报错信息:suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
查看>>
Ubuntu 16.04 部署自己的私有 Docker Registry
查看>>
python打印详细的异常信息
查看>>
FastDFS+Nginx安装配置笔记
查看>>
Nginx配置文件nginx.conf中文注释
查看>>
20120520 linux下mysql的卸载
查看>>
BIND和DNS名称解析
查看>>
hadoop基本操作命令
查看>>
大型web项目解决方案
查看>>
根据模型大小,限定摄像头旋转角度(上,下,左,右)
查看>>