前言:本文主要介绍使用Hibernate映射一对一的关联关系的两种方式:使用外键映射、使用主键映射。

1.数据库表的一对一关联关系

    本文根据客户信息表(tb_customer)和地址信息表(tb_address)来说明其一对一的关系,每一个客户都有一个家庭住址,而每一个地址都对应一个客户。
(1)使用外键映射的数据库表说明
    数据库表模型图如下:
     
    数据库建表语句如下:
  1. CREATE TABLE tb_customer
  2. (
  3. id bigint NOT NULL auto_increment COMMENT 'ID',
  4. name varchar(50) NOT NULL COMMENT '客户名称',
  5. home_address bigint COMMENT '客户家庭地址',
  6. PRIMARY KEY (id)
  7. ) COMMENT = '客户信息表';

  8. CREATE TABLE tb_address
  9. (
  10. id bigint NOT NULL auto_increment COMMENT 'ID',
  11. zipcode varchar(50) NOT NULL COMMENT '邮政编码',
  12. address varchar(200) NOT NULL COMMENT '地址',
  13. PRIMARY KEY (id)
  14. ) COMMENT = '地址信息表';
  15. -- 可选的外键约束
  16. ALTER TABLE tb_customer ADD CONSTRAINT fk_tb_customer_tb_address_1 FOREIGN KEY (home_address) REFERENCES tb_address (id);
(2)使用主键映射的数据库表关系
    数据库表模型图如下:
    
    数据库建表语句如下:
  1. CREATE TABLE tb_customer
  2. (
  3. id bigint NOT NULL auto_increment COMMENT 'ID',
  4. name varchar(50) NOT NULL COMMENT '客户名称',
  5. PRIMARY KEY (id)
  6. ) COMMENT = '客户信息表';

  7. CREATE TABLE tb_address
  8. (
  9. id bigint NOT NULL auto_increment COMMENT 'ID',
  10. zipcode varchar(50) NOT NULL COMMENT '邮政编码',
  11. address varchar(200) NOT NULL COMMENT '地址',
  12. PRIMARY KEY (id)
  13. ) COMMENT = '地址信息表';
  14. -- 可选的外键约束
  15. ALTER TABLE tb_address ADD CONSTRAINT fk_tb_address_tb_customer_1 FOREIGN KEY (id) REFERENCES tb_customer (id);
(3)编写实体类如下
    虽然使用外键关联与使用主键关联在数据库层面上表结构不同,但是对于实体类来说这种关联关系是一样的,所以实体类是一样的,代码如下:
  1. package model;
  2. public class Address
  3. {
  4. private Long id;
  5. private String zipcode;
  6. private String address;
  7. private Customer customer;
  8. @Override
  9. public String toString()
  10. {
  11. return "Address [id=" + id + ", zipcode=" + zipcode + ", address=" + address + ", customer=" + customer.getName() + "]";
  12. }
  13. // 省略setter、getter...
  14. }
  1. package model;
  2. public class Customer
  3. {
  4. private Long id;
  5. private String name;
  6. private Address homeAddress;
  7. @Override
  8. public String toString()
  9. {
  10. return "Customer [id=" + id + ", name=" + name + ", homeAddress=" + homeAddress.getAddress() + "]";
  11. }
  12. // 省略setter、getter...
  13. }
    注意:这里的toString()方法只输出实体类的基本属性,如:", homeAddress=" + homeAddress.getAddress(),而不输出整个实体类(", homeAddress=" + homeAddress),是因为这样做很容易造成循环输出,形成死循环!

2.按照外键映射一对一关联

    使用外键映射一对一关联需要使用many-to-one元素和one-to-one元素,并且在外键方使用many-to-one元素配置外键。配置如下:
  1. <hibernate-mapping package="model">
  2. <class name="Address" table="tb_address">
  3. <id name="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="zipcode" column="zipcode" />
  7. <property name="address" column="address" />
  8. <one-to-one name="customer" class="model.Customer" property-ref="homeAddress"/>
  9. </class>
  10. </hibernate-mapping>
  1. <hibernate-mapping package="model">
  2. <class name="Customer" table="tb_customer">
  3. <id name="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="name" column="name" />
  7. <many-to-one name="homeAddress" class="model.Address" column="home_address" unique="true" cascade="all"/>
  8. </class>
  9. </hibernate-mapping>
    根据上面配置需要注意一下几点:
    1. 在外键方使用many-to-one元素配置外键,如:<many-to-one column="home_address" 。
    2. 在外键参照的主键方要使用one-to-one元素映射关联对象,如:<one-to-one name="customer" class="model.Customer" 。
    3. 在many-to-one元素中要配置unique属性值为true,表明每个Customer对象都有唯一的Address对象关联,形成一对一。
    4. 在many-to-one元素中建议配置cascade属性值为all,表明保存、更新、删除Customer对象会级联操作Address对象。
    5. 在one-to-one元素中要配置property-ref属性值为homeAddress,表明建立了从Customer对象的homeAddress属性到Address对象的关系。
    编写如下的测试程序,测试关联关系,程序代码以及打印结果如下:
  1. public static void main(String[] args)
  2. {
  3. Customer customer;
  4. Address address;
  5. Configuration cfg = new Configuration();
  6. cfg.configure();
  7. ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
  8. SessionFactory sf = cfg.buildSessionFactory(sr);
  9. System.out.println("连接数据库");
  10. Session session = sf.openSession();
  11. Transaction transaction = session.beginTransaction();
  12. try
  13. {
  14. customer=new Customer();
  15. address=new Address();
  16. customer.setName("测试客户01");
  17. address.setZipcode("123456");
  18. address.setAddress("湖北省武汉市");

  19. customer.setHomeAddress(address);
  20. address.setCustomer(customer);
  21. session.save(customer);//配置使用了级联保存
  22. transaction.commit();
  23. }
  24. catch (Exception e)
  25. {
  26. transaction.rollback();
  27. System.out.println("错误:" + e);
  28. }
  29. finally
  30. {
  31. session.close();
  32. System.out.println("关闭数据库");
  33. }
  34. System.exit(0);
  35. }
  1. 连接数据库
  2. Hibernate: insert into tb_address (zipcode, address) values (?, ?)
  3. Hibernate: insert into tb_customer (name, home_address) values (?, ?)
  4. 关闭数据库
    注意:由于配置了级联保存,所以调用session.save(customer)时,会保存customer和address两个对象!

3.按照主键映射一对一关联

    使用主键映射一对一关联只需要使用one-to-one元素配置,配置如下:
  1. <hibernate-mapping package="model">
  2. <class name="Address" table="tb_address">
  3. <id name="id">
  4. <generator class="foreign">
  5. <param name="property">customer</param>
  6. </generator>
  7. </id>
  8. <property name="zipcode" column="zipcode" />
  9. <property name="address" column="address" />
  10. <one-to-one name="customer" class="model.Customer" constrained="true"/>
  11. </class>
  12. </hibernate-mapping>
  1. <hibernate-mapping package="model">
  2. <class name="Customer" table="tb_customer">
  3. <id name="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="name" column="name" />
  7. <one-to-one name="homeAddress" class="model.Address" cascade="all"/>
  8. </class>
  9. </hibernate-mapping>
    对于上面配置需要注意一下几点:
    1. 在Address对象的映射配置中的one-to-one元素属性constrained="true",表示tb_address表的ID主键同时作为外键参照tb_customer表的ID主键,此时Address对象的OID生成策略必须使用foreign。
    2. Address主键生成使用了foreign策略,Hibernate就会保证对象与关联的对象共享同一个OID。
    3. 在Customer对象映射配置文件中建议配置cascade="all",表明保存、更新、删除Customer对象会级联操作Address对象。
    再次运行前面的测试程序,控制台输出结果如下:
  1. 连接数据库
  2. Hibernate: insert into tb_customer (name) values (?)
  3. Hibernate: insert into tb_address (zipcode, address) values (?, ?)
  4. 关闭数据库

4.相关配置详解

(1)one-to-one节点配置详解
  1. <one-to-one name="PropertyName"
  2. access="field|property"
  3. class="ClassName"
  4. property-ref="PropertyNameFromAssociatedClass"
  5. constrained="true|false"
  6. formula="arbitrary SQL expression"
  7. cascade="all|none|save-update|delete"
  8. fetch="join|select"
  9. outer-join="true|false"
  10. foreign-key="foreign-key"
  11. lazy="true|false"
  12. embed-xml="true|false"
  13. entity-name="EntityName"
  14. node="element-name"/>
    如上展示了one-to-one节点常用的配置,是面对其配置进行详细的说明:
  1. name:实体类属性名。
  2. access:默认的实体类属性访问模式,取值为property表示访问getter、setter方法间接访问实体类字段,取值为field表示直接访问实体类字段(类成员变量)。
  3. class:关联的类的名字,默认是通过反射得到属性类型。
  4. property-ref:指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。
  5. constrained:表示使用主键关联一对一关系,一张表的主键同时也是外键,参照另一张表的主键。
  6. formula:一个SQL表达式,定义了这个计算属性的值,计算属性没有和它对应的数据库字段。
  7. cascade:指明哪些操作会从父对象级联到关联的对象。
  8. fetch:参数指定了关联对象抓取的方式是select查询还是join查询,默认为select。fetch="join"等同于outer-join="true",fetch="select"等同于outer-join="false"。
  9. outer-join:设置Hibernate是否使用外连接获取关联的数据,设置成true可以减少SQL语句的条数。
  10. foreign-key:关联的数据库外键名。
  11. lazy:是否采用延迟加载策略。
  12. embed-xml:如果embed-xml="true",则对应于被关联实体或值类型的集合的XML树将直接嵌入拥有这些关联的实体的XML树中,默认值为true。
  13. entity-name:Hibernate3新增特性,用于动态模型(Dynamic Model)支持。Hibernate3允许一个类进行多次映射(前提是映射到不同的表)。
  14. node:配置说明。
-------------------------------------------------------------------------------------------------------------------------------

04.Hibernate一对一关联的更多相关文章

  1. Hibernate一对一关联映射配置

    一.一对一关联 Hibernate提供了两种映射一对一关联关系的方式:按照外键映射和按照主键映射.下面以员工账号和员工档案表为例,介绍这两种映射方式,并使用这两种映射方式分别完成以下持久化操作: (1 ...

  2. 【学习笔记】Hibernate 一对一关联映射 组件映射 二级缓存 集合缓存

    啊讲道理放假这十天不到啊 感觉生活中充满了绝望 这就又开学了 好吧好吧继续学习笔记?还是什么的 一对一关联映射 这次我们仍然准备了两个表 一个是用户表Users 一个是档案表Resume 他们的关系是 ...

  3. Hibernate 一对一关联映射,mappedBy参数解析

    在最近java,SSH框架的学习中遇到了这样的一个问题,在Hibernate的开发中一对一关联映射的单向关联,主表会在次表新增一列次表的主键如下图,但是在双向关联中次表不会在表中创建主表的主键一列,这 ...

  4. hibernate一对一关联

    hibernate一对一主键关联 一对一主键关联指的是两个表通过主键形成的一对一映射. 数据表要求:A表的主键也是B表的主键同时B表的主键也是A表的外键 sql: create table peopl ...

  5. Hibernate 一对一关联查询

    版权声明:本文为博主原创文章,如需转载请标注转载地址. 博客地址:http://www.cnblogs.com/caoyc/p/5602418.html  一对一关联,可以分为两种.一种是基于外键的关 ...

  6. Hibernate 一对一关联映射

    package com.entity; import javax.persistence.Entity; import javax.persistence.OneToOne; @Entity publ ...

  7. hibernate一对一关联手动改表后No row with the given identifier exists:

    articleId手动改了一个并不存在的值 把被控端的id改成存在的就好了

  8. hibernate一对一外键双向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  9. hibernate一对一外键单向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

随机推荐

  1. What is the difference between differed processing mode and interactive mode?

     Every time you access and navigate through the fields on a page in PeopleSoft there are events such ...

  2. jquery.pagination +JSON 动态无刷新分页

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="SqlPage.aspx.cs& ...

  3. .Net 内存泄露

    一.事件引起的内存泄露 1.不手动注销事件也不发生内存泄露的情况 我们经常会写EventHandler += AFunction; 如果没有手动注销这个Event handler类似:EventHan ...

  4. 一款jQuery实现重力弹动模拟效果特效,弹弹弹,弹走IE6

    一款jQuery实现重力弹动模拟效果特效 鼠标经过两块黑色div中间的红色线时,下方的黑快会突然掉落, 并在掉落地上那一刻出现了弹跳的jquery特效效果,非常不错,还兼容所有的浏览器, 适用浏览器: ...

  5. 【转】Messagedlg

      ) = mrYes then Close; MessageDlg用法 对话框类型:mtwarning——含有感叹号的警告对话框mterror——含有红色叉符号的错误对话框mtinformation ...

  6. android 模拟按键事件

    模拟按键事件可以提高代码的复用性,比如在一个edittext的回车事件里做的一些处理 在该edittext的另一个输入要做相同的处理时,模拟按键事件就非常方便了. 代码很简单,直接上代码: new T ...

  7. C#高级功能(一)Lambda 表达式

    Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数. Lambda 表达式对于编写 LINQ ...

  8. Java 第五天 Spring IOC 配置文件

    Spring xml结构定义文件: http://www.springframework.org/schema/beans/spring-beans.xsd 可用xsd列表: http://www.s ...

  9. 第二十章 数据访问(In .net4.5) 之 使用LINQ

    1. 概述 .net3.5中新添加给C#的LINQ查询,提供了直观便捷的数据查询方式.并且支持多种数据源的查询. 本章介绍标准的LINQ操作,如何用最优的方式使用LINQ 以及 LINQ to XML ...

  10. python3.3中使用tornado.options.parse_config_file的时候,在windows下conf为utf-8时,报错的问题

    由于我的windows7下的默认编码是gbk 在调用tornado.options.parse_config_file时,内部代码为 with open(path) as f: exec_in(f.r ...