04.Hibernate一对一关联

前言:本文主要介绍使用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:配置说明。

-------------------------------------------------------------------------------------------------------------------------------

来自为知笔记(Wiz)

时间: 2024-08-10 17:17:30

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

hibernate一对一关联

hibernate一对一主键关联 一对一主键关联指的是两个表通过主键形成的一对一映射. 数据表要求:A表的主键也是B表的主键同时B表的主键也是A表的外键 sql: create table people( id int primary key auto_increment, name varchar(100) not null, sex varchar(100) not null, age int ) create table idcard( id int primary key, idcard

006——hibernate一对一关联映射

一对一关联映射有两种方式:主键关联和外键关联 以夫妻为例(Husband----Wife) 单向关联实体类: Husband.java package com.java.hibernate; public class Husband { private int id; private String name; private Wife wife; public Wife getWife() { return wife; } public void setWife(Wife wife) { thi

Hibernate 一对一关联查询

一对一关联,可以分为两种.一种是基于外键的关联,另一种是基于主键的关联.如图 一.基于外键的方式 User.java 1 package com.proc.one2one; 2 3 public class User { 4 5 private Integer id; 6 private String name; 7 private IdCard card; 8 public User() { 9 } 10 public User(String name) { 11 this.name = na

Hibernate一对一关联映射配置

一.一对一关联 Hibernate提供了两种映射一对一关联关系的方式:按照外键映射和按照主键映射.下面以员工账号和员工档案表为例,介绍这两种映射方式,并使用这两种映射方式分别完成以下持久化操作: (1)保存员工档案的同时分配给员工一个账号. (2)加载员工档案的同时加载账号信息. 按照外键映射: 关系图: ①创建实体类:Resume.Users 并封装属性 public class Resume { //档案id private Integer resid; //档案名称 private Str

hibernate.一对一关联

实体类关系 一对一 一对多 多对一 多对多 Hibernate提供了两种映射一对一关联关系的方式:按照外键映射和按照主键映射.下面以员工账号和员工档案表为例,介绍这两种映射方式,并使用这两种映射方式分别完成以下持久化操作: (1)保存员工档案的同时分配给员工一个账号. (2)加载员工档案的同时加载账号信息. 1.按照外键映射 步骤一:创建实体类Users1和Resume1 Users1创建如下: public class Users1 { private Integer userid; priv

Hibernate 一对一关联映射

package com.entity; import javax.persistence.Entity; import javax.persistence.OneToOne; @Entity public class Husband extends BaseEntity { @OneToOne(mappedBy = "husband") private Wife wife; public Wife getWife() { return wife; } public void setWi

HIBERNATE一对一双向外键联合主键关联

HIBERNATE一对一双向外键联合主键关联: 一. 创建主键类:这个主键必须实现serializedable接口和重写其中的hashCode方法和equals方法:为主键类添加一个叫做@Embeddable的注解和为实体类添加一个叫做@EmbeddabledId的注解

Hibernate一对一映射关联

Hibernate提供了两种一对一映射关联关系的方式: 1)按照外键映射 2)按照主键映射 下面以员工账号表和员工档案表(员工账号和档案表之间是一对一的关系)为例,介绍这两种映射关系,并使用这两种 映射方式分别完成以下持久化操作 (1)保存员工档案的同时分配给员工一个账号 (2)加载员工档案的同时加载账号信息 一:按照外键映射 HibernateUtil工具类(用于获取session和关闭session) package cn.util; import org.hibernate.Session

Hibernate中一对一关联映射/组件映射

Hibernate映射:一对一关联 1.按照外键映射 2.按照主键映射 组件映射 下面以员工账号表和员工档案表(员工账号和档案表之间是一对一的关系)为例,介绍这两种映射关系,并使用这两种 映射方式分别完成以下持久化操作 (1)保存员工档案的同时分配给员工一个账号 (2)加载员工档案的同时加载账号信息 一:按照外键映射