Ohhnews

分类导航

$ cd ..
Baeldung原文

Hibernate @EmbeddedTable 注解指南

#hibernate#嵌入式映射#注解#数据持久化#表映射

1. 概述

@EmbeddedTable 注解是 Hibernate 的一项新特性,它简化了将嵌入对象映射到辅助表的逻辑。

在本篇简短教程中,我们将深入探讨该注解的含义及其用法。首先,我们会了解引入 @EmbeddedTable 的动机,然后通过实际示例演示如何使用它。

2. 传统映射存在的问题

在这个新注解出现之前,JPA 提供了多种注解来将单个实体映射到多个表。然而,传统方法需要结合使用 @SecondaryTable@Embedded@Embeddable 以及多个 @AttributeOverride 注解来逐个覆盖每个列。随着列数的增加,这种方式会迅速变得冗长

假设我们有一个 Person 实体,它存储个人信息和地址信息。这里,我们打算将地址详情存储在一个单独的辅助表中

首先,创建一个我们希望嵌入到 Person 实体中的 Address 对象:

$ java
@Embeddable
public class Address {
	
    private String street;
    private String city;
    private String code;
    // setters
    
}

现在,创建 Person 实体:

$ java
@Entity
@SecondaryTable(name = "person_address")
public class Person {
    
    @Id
    private int id;
    
    @Column(name= "first_name")
    private String firstName;
    
    @Column(name = "last_name")
    private String lastName;
    
    @Embedded 
    private Address address;
    // setters
}

这还不够,因为将 Address 字段映射到辅助表需要为每个字段使用 @AttributeOverride 注解

$ java
@Embedded 
@AttributeOverride(name = "street", column = @Column(table = "person_address")) 
@AttributeOverride(name = "city", column = @Column(table = "person_address"))
@AttributeOverride(name = "code", column = @Column(table = "person_address"))
private Address address;

这种方法很快就会变得繁琐且容易出错,因为遗漏任何一个覆盖都可能导致列被静默地映射到错误的表。这就是 @EmbeddedTable 发挥作用的地方。

3. 使用 @EmbeddedTable

从 Hibernate 7.2 开始,我们可以使用 @EmbeddedTable 更简洁地实现与上一节相同的映射:

$ java
@EmbeddedTable(value = "person_address")
private Address address;

简而言之,Hibernate 会自动将嵌入对象 Address 的每个字段映射到指定的辅助表 person_address,而无需逐个覆盖每个字段

这在处理包含多个字段的大型可嵌入对象时特别有用

因此,我们添加一个测试用例来确认一切正常:

$ java
@Test
void whenUsingEmbeddedTableThenMapIntoTwoSeparateTables() {
    Address address = new Address();
    address.setStreet("12 Av. Tamassint center");
    address.setCity("Tamassint");
    address.setCode("10000");
    Person person = new Person();
    person.setId(1);
    person.setFirstName("Azhrioun");
    person.setLastName("Abderrahim");
    person.setAddress(address);
    session.persist(person);
    session.flush();
    Object[] addressRow = (Object[]) session.createNativeQuery(
      "select street, city from person_address",
      Object[].class
    ).uniqueResult();
    assertEquals("12 Av. Tamassint center", addressRow[0]);
    assertEquals("Tamassint", addressRow[1]);
    Object[] personRow = (Object[]) session.createNativeQuery(
      "select first_name, last_name from person",
      Object[].class
    ).uniqueResult();
    assertEquals("Azhrioun", personRow[0]);
    assertEquals("Abderrahim", personRow[1]);
}

不出所料,测试用例成功通过。

4. 局限性

尽管使用方便,但在使用 @EmbeddedTable 时仍有几点需要注意。

首先,它是 Hibernate 特有的注解,不属于 Jakarta Persistence 规范 的一部分。如果跨 JPA 提供程序的可移植性很重要,那么 @AttributeOverride 注解始终是更安全的选择

此外,@EmbeddedTable 被标记为 @Incubating,这意味着该 API 仍在演变中,尚未被认为是稳定和成熟的。

通常,@EmbeddedTable 是为顶层的嵌入对象设计的,因此尚不支持在嵌套对象上使用。

5. 结论

在这篇简短的文章中,我们探讨了新的 Hibernate @EmbeddedTable 注解。

通过讲解,我们了解到它在将嵌入对象映射到辅助表时,提供了一种比多个 @AttributeOverride 注解更清晰的替代方案。

完整源代码可在 GitHub 上找到。