8.1.2 Hibernate:一对一双向关联(bidirectional)

1 定义映射类
1.1 表 phone 的映射类定义:

package hibernate;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "phone")
public class Phone {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "imei")
    private String imei;

    @Column(name = "number")
    private String number;

    @OneToOne(mappedBy = "phone", orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private PhoneDetail phoneDetail;

    public Phone() {}

    public Phone(String imei, String number) {
        this.imei = imei;
        this.number = number;
    }

    // 省略 Getters 和 Setters ...

}

1.2 表 phone_detail 的映射类定义:

package hibernate;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "phone_detail")
public class PhoneDetail {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "manufacturer")
    private String manufacturer;

    @Column(name = "model")
    private String model;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "phone_id")
    private Phone phone;

    public PhoneDetail() {}

    public PhoneDetail(String manufacturer, String model) {
        this.manufacturer = manufacturer;
        this.model = model;
    }

    // 省略 Getters 和 Setters ...

}

2 测试
2.1 新增

@Test
public void test() {
    Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();
    Phone phone = new Phone("812345678912345", "18012345678");
    PhoneDetail phoneDetail = new PhoneDetail("XXX", "XXX-2017");
    phone.setPhoneDetail(phoneDetail);
    phoneDetail.setPhone(phone);
    session.save(phone);
    transaction.commit();
    session.close();
    sessionFactory.close();
}

运行测试,数据库表 phonephone_detail 中新插入了两条数据(日志省略)。

将单元测试中 session.save(phone); 替换成 session.save(phoneDetail);,测试结果相同。

由此可见,双向关联的任一方都维护级联关系。

2.2 删除
基于以上测试新增的数据进行删除测试。

@Test
public void test() {
    Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();
    Phone phone = (Phone) session.createQuery(" FROM Phone").list().get(0);
    session.delete(phone);
    transaction.commit();
    session.close();
    sessionFactory.close();
}

运行测试,数据库表 phonephone_detail 中对应记录被删除(日志省略)。

将单元测试中

Phone phone = (Phone) session.createQuery(" FROM Phone").list().get(0);
session.delete(phone);

替换成

PhoneDetail phoneDetail = (PhoneDetail) session.createQuery(" FROM PhoneDetail").list().get(0);
session.delete(phoneDetail);

测试结果相同。

2.3 更新
基于新增测试的数据进行更新测试。
2.3.1 通过 Phone 查找关联的 PhoneDetail 并执行级联更新

@Test
public void test() {
    Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();
    Phone phone = (Phone) session.createQuery(" FROM Phone").list().get(0);
    phone.setImei("898765432198765");
    phone.setNumber("17712345678");
    PhoneDetail phoneDetail = phone.getPhoneDetail();
    phoneDetail.setManufacturer("YYY");
    phoneDetail.setModel("YYY-2017");
    session.save(phone);
    transaction.commit();
    session.close();
    sessionFactory.close();
}

运行测试,数据库表 phonephone_detail 中对应记录级联更新成功(日志省略)。

将单元测试中 session.save(phone); 替换成 session.save(phoneDetail);,测试结果相同,同样级联更新成功。

2.3.1 通过 PhoneDetail 查找关联的 Phone 并执行级联更新

@Test
public void test() {
    Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();
    PhoneDetail phoneDetail = (PhoneDetail) session.createQuery(" FROM PhoneDetail").list().get(0);
    phoneDetail.setManufacturer("YYY");
    phoneDetail.setModel("YYY-2017");
    Phone phone = phoneDetail.getPhone();
    phone.setImei("898765432198765");
    phone.setNumber("17712345678");
    session.save(phoneDetail);
    transaction.commit();
    session.close();
    sessionFactory.close();
}

运行测试,数据库表 phonephone_detail 中对应记录级联更新成功(日志省略)。

将单元测试中 session.save(phoneDetail); 替换成 session.save(phone);,测试结果相同,同样级联更新成功。

2.4 查询
基于新增测试的数据进行查询测试。

@Test
public void test() {
    Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();
    Phone phone = (Phone) session.createQuery(" FROM Phone").list().get(0);
    System.out.println("-------------------- From Phone --------------------");
    System.out.println("Phone ID : " + phone.getId());
    System.out.println("Phone IMEI : " + phone.getImei());
    System.out.println("Phone Number : " + phone.getNumber());
    System.out.println("Binded Phone Detail ID : " + phone.getPhoneDetail().getId());
    System.out.println("Binded Phone Detail Manufacture : " + phone.getPhoneDetail().getManufacturer());
    System.out.println("Binded Phone Detail Model : " + phone.getPhoneDetail().getModel());
    System.out.println("----------------------------------------------");
    PhoneDetail phoneDetail = (PhoneDetail) session.createQuery(" FROM PhoneDetail").list().get(0);
    System.out.println("-------------------- From Phone Detail --------------------");
    System.out.println("Phone Detail ID : " + phoneDetail.getId());
    System.out.println("Phone Detail Manufacture : " + phoneDetail.getManufacturer());
    System.out.println("Phone Detail Model : " + phoneDetail.getModel());
    System.out.println("Binded Phone ID : " + phoneDetail.getPhone().getId());
    System.out.println("Binded Phone IMEI : " + phoneDetail.getPhone().getImei());
    System.out.println("Binded Phone Number : " + phoneDetail.getPhone().getNumber());
    System.out.println("----------------------------------------------");
    transaction.commit();
    session.close();
    sessionFactory.close();
}

运行测试,打印结果:

......
-------------------- From Phone --------------------
Phone ID : 15
Phone IMEI : 898765432198765
Phone Number : 17712345678
Binded Phone Detail ID : 11
Binded Phone Detail Manufacture : YYY
Binded Phone Detail Model : YYY-2017
----------------------------------------------
......
-------------------- From Phone Detail --------------------
Phone Detail ID : 11
Phone Detail Manufacture : YYY
Phone Detail Model : YYY-2017
Binded Phone ID : 15
Binded Phone IMEI : 898765432198765
Binded Phone Number : 17712345678
----------------------------------------------
......
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

又言又语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值