hibernate 一对一(One-to-One)

阅读更多

转:http://ryxxlong.iteye.com/blog/622652

一对一(one-to-one)实例(Person-IdCard)

一对一的关系在数据库中表示为主外关系.例如.人和身份证的关系.每个人都对应一个身份证号.我们应该两个表.一个是关于人信息的表(Person).别外一个是身份证相关信息的表(id_card).id_card表的主键对应该Person表的主键id,也是Person表的外键.有人才能有身份证.所以此例中Person是主表,id_card表为从表。

hibernate的一对一关系有两种形式,一种是共享主键方式,另一种是唯一外键方式.

一、共享主键方式实现一对一

1. 实体类设计如下:

Person类:

Java代码   收藏代码
  1. package com.reiyen.hibernate.domain;  
  2.   
  3. public class Person {  
  4.   
  5.     private int id;  
  6.     private String name;  
  7.     private IdCard idCard;  
  8.   
  9.        //setter和getter方法  
  10. }  

 IdCard类:

Java代码   收藏代码
  1. package com.reiyen.hibernate.domain;  
  2.   
  3. public class IdCard {  
  4.   
  5.     private int id;  
  6.     private Date authorizeDate;  
  7.     private Person person;  
  8.          
  9.        //setter和getter方法  
  10. }  

 2.映射文件:

Person.hbm.xml文件如下:

Xml代码   收藏代码
  1. xml version="1.0"?>  
  2.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <hibernate-mapping package="com.reiyen.hibernate.domain">  
  5.     <class name="Person" >  
  6.         <id name="id" >  
  7.             <generator class="native" />  
  8.         id>  
  9.         <property name="name" />  
  10.         <one-to-one name="idCard" />  
  11.     class>  
  12. hibernate-mapping>  

 IdCard.hbm.xml文件如下:

Xml代码   收藏代码
  1. xml version="1.0"?>  
  2.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <hibernate-mapping package="com.reiyen.hibernate.domain">  
  5.     <class name="IdCard" table="id_card">  
  6.         <id name="id">  
  7.               
  8.             <generator class="foreign">  
  9.                 <param name="property">personparam>  
  10.             generator>  
  11.         id>  
  12.         <property name="authorizeDate" column="authorize_date" />  
  13.         IdCard ) 
    一对一唯一外键 双向 关联,需要在另一端(person ),添加  标签,指示 hibernate 如何加载 
    其关联对象,默认根据主键加载idcard ,外键关联映射中,因为两个实体采用的是 idcard 的外键维护的关系, 所以不能指定主键加载 idcard ,而要根据 idcard 的外键加载,所以采用如下映射方式: 

    IdCard.hbm.xml的映射文件如下:

     

    Xml代码   收藏代码
    1. xml version="1.0"?>  
    2.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
    3.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
    4. <hibernate-mapping package="com.itcast.hibernate.domain">  
    5.     <class name="IdCard" table="id_card">  
    6.         <id name="id">  
    7.             <generator class="native" />  
    8.         id>  
    9.         <property name="authorizeDate" column="authorize_date" />  
    10.   
    11.         <one-to-one name="idCard" property-ref="person"/>  
    12.     class>  
    13. hibernate-mapping>  

     实体类不用修改,还是用上面的测试类进行测试即可。

    保存测试类运行后,相对共享主键方式的one-to-one,id_card表的结构发生了变化,表结构如下所示:

    DROP TABLE IF EXISTS `test`.`id_card`;
    CREATE TABLE  `test`.`id_card` (
      `id` int(11) NOT NULL AUTO_INCREMENT, 
      `authorize_date` datetime DEFAULT NULL,
      `person_id` int(11) DEFAULT NULL, 
      PRIMARY KEY (`id`),
      UNIQUE KEY `person_id` (`person_id`) ,
      KEY `FK627C1FB45B253C91` (`person_id`),
      CONSTRAINT `FK627C1FB45B253C91` FOREIGN KEY (`person_id`) REFERENCES `person` (`id`) 
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

    数据库表中记录如下:

    mysql> select * from person;
    +----+---------+
    | id | name    |
    +----+---------+
    |  1 | person1 |
    +----+---------+
    1 row in set (0.00 sec)

    mysql> select * from id_card;
    +----+---------------------+-----------+
    | id | authorize_date      | person_id |
    +----+---------------------+-----------+
    |  1 | 2010-03-23 22:40:38 |         1 |
    +----+---------------------+-----------+
    1 row in set (0.00 sec)

     

    如果Person.hbm.xml映射文件中没有这一项的话,运行测试:

    Java代码   收藏代码
    1. Person person = (Person)session.get(Person.class, id);  
    2. System.out.println(person.getIdCard().getAuthorizeDate());  

     会抛出如下异常:

     java.lang.NullPointerException

    因为这种关系成了IdCard--->Person的单向关联了。知道了Person,找不到对应的IdCard.

    当运行如下测试时:

    Java代码   收藏代码
    1. Person person = (Person)session.get(Person.class, id);  
    2. System.out.println(person.getIdCard());  

     控制台会打印出Person相对应的IdCard为null.

     

    但如果得到了IdCard,却能找到相应的Person.测试如下:

    Java代码   收藏代码
    1. IdCard idCard = (IdCard)session.get(IdCard.class, id);  
    2. System.out.println(idCard.getPerson().getName());  

     能得到正常的结果,person name为person1.

    总结: 在缺省情况下,hibernate只有在一对一关联中,查询主对象时,是进行关联查询一次得到查询结果,其它(多对多、多对一、一对多、一对一查询从对象)的查询都是分两次查询得到查询结果。

你可能感兴趣的:(hibernate)