Hibernate4-6 映射一对一关联关系

一对一关联关系详解
本文详细介绍了在ORM框架中实现一对一关联关系的两种方式:基于外键映射和基于主键映射。通过示例代码展示了如何配置关联关系,并提供了数据库操作的测试案例。

  一对一关联关系的概述图如下所示:
这里写图片描述


1. 基于外键映射的1-1关联关系

  对于基于外键映射的1-1关联关系,其外键可以放在任意一端,但不能两边都使用外键映射。
  在需要存放外键的一端:增加many-to-one元素,并设置其unique属性为true来表示1-1关联,示例代码如下:

<!-- 配置多对一映射,并添加唯一性约束 -->
<many-to-one name="manager" class="Manager" column="MGR_ID" unique="true"></many-to-one>

  在不需存放外键的一端:增加one-to-one元素,且必须使用property-ref属性指定使用被关联实体主键以外的字段作为关联字段,示例代码如下:

<!-- 配置一对一映射 -->
<!-- 若不配置property-ref属性,则在左外连接查询时,将使用被关联实体的主键作为关联字段 -->
<one-to-one name="department" class="Department" property-ref="manager"></one-to-one>

  基于外键映射的1-1关联关系的数据库操作测试代码如下所示:

@Test
public void testGet1() {
    // 4. 在查询没有外键的实体对象时,使用左外连接一并查询其关联的对象,并进行初始化
    Manager mgr = (Manager) session.get(Manager.class, 5);
    System.out.println(mgr.getName());
    System.out.println(mgr.getDepartment().getName());
}

@Test
public void testGet() {
    // 1. 默认情况下对关联属性使用懒加载,所以可能会出现懒加载异常的问题
    Department dept = (Department) session.get(Department.class, 5);
    System.out.println(dept.getName());

    // 2. org.hibernate.LazyInitializationException
//  session.close();
//  System.out.println(dept.getManager().getName());

    // 3. 查询Manager对象时左外连接条件有误,需在one-to-one中配置property-ref属性
    System.out.println(dept.getManager().getName());
}

@Test
public void testSave() {
    Department dept = new Department();
    dept.setName("DEPT-AA");

    Manager mgr = new Manager();
    mgr.setName("MGR-AA");

    // 设置1-1关联关系
    dept.setManager(mgr); 
    mgr.setDepartment(dept);

    // 注意:建议先保存没有外键列的对象,以减少UPDATE语句
    session.save(dept);
    session.save(mgr);
}

2. 基于主键映射的1-1关联关系

  主要策略:指一端的主键生成器使用foreign策略,即根据”对方”的主键来生成自己的主键,本身不能自动生成主键。
  在使用foreign主键生成器的一端:增加one-to-one元素,并设置其constrained属性为true,即当前持久化类对应数据库表的主键添加一个外键约束,示例代码如下:

<id name="id" column="MGR_ID" type="java.lang.Integer">
    <!-- 使用外键的方式来生成当前主键 -->
    <generator class="foreign">
        <!-- property属性指定使用当前持久化类的哪一个属性的主键做外键 -->
        <param name="property">department</param>
    </generator>
</id>
<!-- 配置一对一映射:需要为其添加外键约束 -->
<one-to-one name="department" class="Department" constrained="true"></one-to-one>

  在不用foreign主键生成器的一端:增加one-to-one元素映射关联属性即可,示例代码如下:

<!-- 配置一对一映射 -->
<one-to-one name="manager" class="Manager"></one-to-one>

  基于主键映射的1-1关联关系的数据库操作测试代码如下所示:

package com.qiaobc.hibernate.one2one.primary;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHibernate {

    private SessionFactory sessionFactory; // 单实例的
    private Session session; // 项目中不能声明为成员变量,可能会有并发问题
    private Transaction transaction; // 项目中不能声明为成员变量,可能会有并发问题

    @Before
    public void init() {
        // 创建Session对象并开启事务
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(configuration.getProperties())
                .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
    }

    @Test
    public void testGet1() {
        // 4. 在查询有主键约束的实体对象时,使用左外连接一并查询其关联的对象,并进行初始化
        Department dept = (Department) session.get(Department.class, 1);
        System.out.println(dept.getName());
        System.out.println(dept.getManager().getName());
    }

    @Test
    public void testGet() {
        // 1. 默认情况下对关联属性使用懒加载,所以可能会出现懒加载异常的问题
        Manager mgr = (Manager) session.get(Manager.class, 1);
        System.out.println(mgr.getName());

        // 2. org.hibernate.LazyInitializationException
//      session.close();
//      System.out.println(dept.getManager().getName());

        // 3. 查询Department对象时左外连接
        System.out.println(mgr.getDepartment().getName());
    }

    @Test
    public void testSave() {

        Department dept = new Department();
        dept.setName("DEPT-AA");

        Manager mgr = new Manager();
        mgr.setName("MGR-AA");

        // 设置1-1关联关系
        dept.setManager(mgr); 
        mgr.setDepartment(dept);

        // 注意:无论先插入哪一个对象都不会有多余的UPDATE
        session.save(dept);
        session.save(mgr);
    }

    @After
    public void destory() {
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值