JPA @Embedded和@Embeddable

2023/05/18

1. 概述

在本教程中,我们将了解如何将包含嵌入属性的实体映射到单个数据库表。

为此,我们将使用Java Persistence API(JPA)提供的@Embeddable和@Embedded注解。

2. 数据模型上下文

首先,我们定义一个名为company的表。

公司表会存放公司名称、地址、电话等基本信息以及联系人信息:

public class Company {

    private Integer id;

    private String name;

    private String address;

    private String phone;

    private String contactFirstName;

    private String contactLastName;

    private String contactPhone;

    // standard getters, setters
}

但是,跟联系人相关的三个字段似乎应该抽象到一个单独的类中

问题是我们不想为这些细节创建一个单独的表

那么,让我们看看我们能做什么。

3. @Embeddable

JPA提供了@Embeddable注解来声明一个类将被其他实体嵌入

让我们定义一个类来抽象出联系人详细信息:

@Embeddable
public class ContactPerson {

    private String firstName;

    private String lastName;

    private String phone;

    // standard getters, setters
}

4. @Embedded

JPA注解@Embedded用于将一个类型嵌入到另一个实体中

接下来,让我们修改Company类。

我们将添加JPA注解,并改为使用ContactPerson而不是单独的字段:

@Entity
public class Company {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    private String address;

    private String phone;

    @Embedded
    private ContactPerson contactPerson;

    // standard getters, setters
}

因此,我们的Company实体嵌入联系人详细信息并映射到单个数据库表。

不过,我们还有一个问题,那就是JPA如何将这些字段映射到数据库列

5. 属性覆盖

我们的字段在原来的Company类中被命名contactFirstName,现在在我们的ContactPerson类中被命名为firstName。因此,JPA会将它们分别映射到contact_first_name和first_name。

除了不太理想之外,它实际上还会破坏我们现在重复的phone列,因为此时Company和ContactPerson实体中都包含phone属性。

因此,我们可以使用@AttributeOverrides和@AttributeOverride注解来覆盖我们嵌入类型的列属性

让我们将其添加到Company实体中的ContactPerson字段:

@Embedded
@AttributeOverrides({
    @AttributeOverride( name = "firstName", column = @Column(name = "contact_first_name")), 
    @AttributeOverride( name = "lastName", column = @Column(name = "contact_last_name")), 
    @AttributeOverride( name = "phone", column = @Column(name = "contact_phone"))
})
private ContactPerson contactPerson;

请注意,由于这些注解使用在字段上,因此我们可以对每个封闭实体进行不同的覆盖。

6. 总结

在本文中,我们配置了一个具有一些嵌入属性的实体,并将它们映射到与封闭实体相同的数据库表。

为此,我们使用了Java Persistence API提供的@Embedded、@Embeddable、@AttributeOverrides和@AttributeOverride注解。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章