hibernate系列(四)一对一关联关系

以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 

上述一对一的关联关系是通过外键来连接,他们也可以使用相同的主键实现一对一。这里不再讲述。 

时间: 2024-10-27 22:11:02

hibernate系列(四)一对一关联关系的相关文章

Hibernate(5)—— 联合主键 、一对一关联关系映射(xml和注解) 和 领域驱动设计

俗话说,自己写的代码,6个月后也是别人的代码--复习!复习!复习!涉及的知识点总结如下: One to One 映射关系 一对一单向外键(XML/Annotation) 一对一双向外键关联(XML/Annotation) 联合主键 一对一单向外键联合主键(Xml/Annotation) 一对一组件关联(XML/Annotation) 理解组件 领域驱动设计--自动生成数据库脚本 一对一关系的小结 一些出错问题的总结   自动生成数据库脚本 一般在项目开发过程中,我们的习惯是先建好数据库和表,然后

走近Flex组件系列(四):分组组件(Box)、分割组件(DividedBox)和容器组件

走近Flex组件系列(四):分组组件(Box).分割组件(DividedBox)和容器组件(Panel) 本文主要介绍Flex的Box,DividedBox和Panel组件的应用. 一.分组组件(Box) Flex中Box组件分两种,即VBox和HBox,也就是水平分组布局和垂直分组布局.下面对这两中分别进行介绍. Flex的VBox组件可以自动的帮助开发人员在界面布局的时候进行水平分组,所谓的分组也就是他会自动将放置在其内部的其他组件进行水平布局放置,如下mxml代码: 1 <mx:HBox

Ruby on rails开发从头来(五十五)- ActiveRecord基础(一对一关联关系)

一对一关联,或者更正确的说是一对零或一对一关联,是通过外键引用到另外一张表中的至多一条记录实现的,下图描述了orders表和invoices表的关系: 开发从头来(五十五)- ActiveRecord基础(一对一关联关系)-rails activerecord"> 在Active Record中,要表示这样的关系需要在Order类中添加has_one:Invoice声明,并且同时在Invoice类中添加声明belongs_to:order,事实上,我们可以把这种关联关系看作是相互的,我们可

系统学习hibernate之六:一对一外键关联映射双向关联

hibernate一对一唯一外键关联映射(双向关联Person<---->IdCard) 一对一唯一外键关联双向,需要在另一端(idcard),添加<one-to-one>标签,指示hibernate如何加载 其关联对象,默认根据主键加载person,外键关联映射中,因为两个实体采用的是person的外键维护的关系, 所以不能指定主键加载person,而要根据person的外键加载,所以采用如下映射方式: <one-to-one name="person"

在Hibernate中正确实现关联关系中的级联操作(cascading)

关系数据库系统本身就比较复杂,加上Hibernate的O/R映射层,复杂度加重了,很容易出现问题,本人将最近遇到的问题和解决方法做一个总结,整理在下面的一系列文章中 正确理解Hibernate的聚合类型(collection)的使用 在Hibernate中正确实现关联关系中的级联操作(cascading) 在Hibernate框架中编写持久对象类实现外键关联的几点注意事项 本文是第二篇,讲解在one-to-many(一对多)和many-to-one(多对一)关联关系中的cascade特性的声明方

iOS开发UINavigation系列四——导航控制器UINavigationController

iOS开发UINavigation系列四--导航控制器UINavigationController 一.引言         在前面的博客中,我么你介绍了UINavigationBar,UINavigationItem和UIToolBar,UINavigationController是将这些控件和UIViewController紧密的结合了起来,使用导航,我们的应用程序层次会更加分明,对controller的管理也更加方便.前几篇博客地址如下: UINavigationBar:http://my

iOS流布局UICollectionView系列四——自定义FlowLayout进行瀑布流布局

iOS流布局UICollectionView系列四--自定义FlowLayout进行瀑布流布局 一.引言         前几篇博客从UICollectionView的基础应用到设置UICollectionViewFlowLayout更加灵活的进行布局,但都限制在系统为我们准备好的布局框架中,还是有一些局限性,例如,如果我要进行瀑布流似的不定高布局,前面的方法就很难满足我们的需求了,如下: 这种布局无疑在app的应用中更加广泛,商品的展示,书架书目的展示,都会倾向于采用这样的布局方式,当然,通过

xen虚拟化实战系列(四)之xen虚拟机扩展磁盘空间一法

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://koumm.blog.51cto.com/703525/1285460 xen虚拟化实战系列文章列表 xen虚拟化实战系列(一)之xen虚拟化环境安装xen虚拟化实战系列(二)之xen虚拟机安装xen虚拟化实战系列(三)之xen虚拟机复制xen虚拟化实战系列(四)之xen虚拟机扩展磁盘空间一法xen虚拟化实战系列(五)之xen虚拟机扩展磁盘空间再一法xen虚拟化实战系列(六)之x

iOS中CoreData数据管理系列四——进行数据与页面的绑定

iOS中CoreData数据管理系列四--进行数据与页面的绑定 一.引言     在上一篇博客中,我们讨论了CoreData框架中添加与查询数据的操作,事实上,在大多数情况下,这些数据都是由一个UITableView表视图进行展示的,因此,CoreData框架中还未开发者提供了一个类NSFetchedResultsController,这个类作为桥接,将视图与数据进行绑定. 添加与查询数据操作:http://my.oschina.net/u/2340880/blog/611430. 二.进行数据