Overriding Column Definition With @AttributeOverride – 用@AttributeOverride来覆盖列的定义

最后修改: 2021年 5月 17日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll show how to use @AttributeOverride to change a column mapping. We’ll explain how to use it when extending or embedding an entity, and we’ll cover single and collection embedding.

在本教程中,我们将展示如何使用@AttributeOverride来改变一个列的映射。我们将解释在扩展或嵌入实体时如何使用它,我们还将介绍单一和集合嵌入。

2. @AttributeOverride‘s Attributes

2.@AttributeOverride的属性

The annotation contains two mandatory attributes:

该注释包含两个强制性的属性。

  • name – field name of an included entity
  • column – column definition which overrides the one defined in the original object

3. Use With @MappedSuperclass

3.与@MappedSuperclass一起使用

Let’s define a Vehicle class:

让我们定义一个车辆

@MappedSuperclass
public class Vehicle {
    @Id
    @GeneratedValue
    private Integer id;
    private String identifier;
    private Integer numberOfWheels;
    
    // standard getters and setters
}

The @MappedSuperclass annotation indicates that it’s a base class for other entities.

@MappedSuperclass注解表明它是其他实体的基类。

Let’s next define class Car, which extends Vehicle. It demonstrates how to extend an entity and store a car’s information in a single table. Note that the annotation goes on the class:

接下来让我们定义Car类,它扩展了Vehicle. 它演示了如何扩展一个实体并在一个表中存储汽车的信息。请注意,注释在类上:

@Entity
@AttributeOverride(name = "identifier", column = @Column(name = "VIN"))
public class Car extends Vehicle {
    private String model;
    private String name;

    // standard getters and setters
}

As a result, we have one table with all car details together with vehicle details. The thing is that for a car, we want to store an identifier in column VIN. We achieve it with @AttributeOverride. The annotation defines that field identifier is stored in the VIN column. 

因此,我们有一个表,里面有所有的汽车细节和车辆细节。问题是,对于一辆车,我们想在列VIN中存储一个标识符。我们通过@AttributeOverride来实现。该注解定义了字段标识符被存储在VIN列中。

4. Use With an Embedded Class

4.与一个嵌入式班级一起使用

Let’s now add more details to our vehicle with two embeddable classes.

现在让我们用两个可嵌入的类为我们的车辆添加更多细节。

Let’s first define basic address information:

首先让我们定义一下基本的地址信息。

@Embeddable
public class Address {
    private String name;
    private String city;

    // standard getters and setters
}

Let’s also create a class with car manufacturer information:

让我们也创建一个带有汽车制造商信息的类。

@Embeddable
public class Brand {
    private String name;
    private LocalDate foundationDate;
    @Embedded
    private Address address;

    // standard getters and setters
}

The Brand class contains an embedded class with address details. We’ll use it to demonstrate how to use @AttributeOverride with multiple levels of embedding.

品牌类包含一个嵌入的类,其中有地址的详细信息。我们将用它来演示如何使用@AttributeOverride 与多层次的嵌入。

Let’s extend our Car with Brand details:

让我们扩展我们的汽车品牌的细节。

@Entity
@AttributeOverride(name = "identifier", column = @Column(name = "VIN"))
public class Car extends Vehicle {
    // existing fields

    @Embedded
    @AttributeOverrides({
      @AttributeOverride(name = "name", column = @Column(name = "BRAND_NAME", length = 5)),
      @AttributeOverride(name = "address.name", column = @Column(name = "ADDRESS_NAME"))
    })
    private Brand brand;

    // standard getters and setters
}

First of all, the @AttributeOverrides annotation allows us to modify more than one attribute. We’ve overridden the name column definition from the Brand class because the same column exists in the Car class. As a result, the brand name is stored in column BRAND_NAME.

首先,@AttributeOverrides注解允许我们修改一个以上的属性。我们从品牌类中覆盖了名称列的定义,因为同一列存在于汽车类中。因此,品牌名称被存储在列BRAND_NAME中。

Furthermore, we’ve defined column length to show that not only a column name can be overridden. Note that the column attribute overrides all values from the overridden class. To keep original values, all must be set in column attributes.

此外,我们定义了列的长度,以表明不仅仅是一个列名可以被覆盖。请注意,column属性覆盖了被覆盖类的所有值。为了保持原来的值,所有必须在column属性中设置

In addition to that, the name column from the Address class has been mapped to ADDRESS_NAME. To override mappings at multiple levels of embedding, we use a dot “.” to specify a path to the overridden field.

除此之外,来自Address类的name列已经被映射到ADDRESS_NAME为了在多级嵌入中覆盖映射,我们使用一个点”. “来指定覆盖字段的路径

5. Embedded Collection

5.嵌入收集

Let’s play a little bit with this annotation and see how it works with a collection.

让我们来玩一下这个注释,看看它是如何在一个集合中工作的。

Let’s add a car’s owner details:

让我们添加一个车主的详细资料。

@Embeddable
public class Owner {
    private String name;
    private String surname;

    // standard getters and setters
}

We want to have an owner together with an address, so let’s add a map of owners and their addresses:

我们希望所有者与地址一起,所以让我们添加一个所有者及其地址的地图

@Entity
@AttributeOverride(name = "identifier", column = @Column(name = "VIN"))
public class Car extends Vehicle {
    // existing fields

    @ElementCollection
    @AttributeOverrides({
      @AttributeOverride(name = "key.name", column = @Column(name = "OWNER_NAME")),
      @AttributeOverride(name = "key.surname", column = @Column(name = "OWNER_SURNAME")),
      @AttributeOverride(name = "value.name", column = @Column(name = "ADDRESS_NAME")),
    })
    Map<Owner, Address> owners;

    // standard getters and setters
}

Thanks to the annotation, we can reuse the Address class. The key prefix indicates an override of a field from the Owner class. Furthermore, a value prefix points to the field from the Address class. For lists, no addition prefix is required.

由于注解的存在,我们可以重复使用Addresskey前缀表示对Owner类中一个字段的覆盖。此外,value前缀指向来自Address类的字段。对于列表,不需要添加前缀。

6. Conclusion

6.结论

That concludes this short article about the @AttibuteOverride annotation. We’ve seen how to use this annotation when extending or embedding an entity. After that, we’ve learned how to use it with a collection.

关于@AttibuteOverride注解的这篇短文到此结束。我们已经看到了在扩展或嵌入一个实体时如何使用这个注解。之后,我们学习了如何在一个集合中使用它。

As always, the source code of the example is available over on GitHub.

一如既往,该示例的源代码可在GitHub上获得over