Java JPA和Hibernate中@MapKey、@MapKeyColumn和@MapKeyJoinColumn的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25439813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:24:01  来源:igfitidea点击:

Difference between @MapKey, @MapKeyColumn and @MapKeyJoinColumn in JPA and Hibernate

javahibernatejpaormhibernate-mapping

提问by Chaitanya

As per Hibernate documentation, there are multiple annotations available if we want to use Map as an association between our entities. The doc says:

根据Hibernate 文档,如果我们想使用 Map 作为实体之间的关联,则有多个注释可用。医生说:

Alternatively the map key is mapped to a dedicated column or columns. In order to customize the mapping use one of the following annotations:

@MapKeyColumn if the map key is a basic type. If you don't specify the column name, the name of the property followed by underscore followed by KEY is used (for example orders_KEY). @MapKeyEnumerated / @MapKeyTemporal if the map key type is respectively an enum or a Date. @MapKeyJoinColumn/@MapKeyJoinColumns if the map key type is another entity. @AttributeOverride/@AttributeOverrides when the map key is a embeddable object. Use key. as a prefix for your embeddable object property names. You can also use @MapKeyClass to define the type of the key if you don't use generics.

或者,映射键被映射到一个或多个专用列。为了自定义映射,请使用以下注释之一:

@MapKeyColumn 如果映射键是基本类型。如果不指定列名,则使用属性名称后跟下划线后跟 KEY(例如 orders_KEY)。@MapKeyEnumerated / @MapKeyTemporal 如果映射键类型分别是枚举或日期。@MapKeyJoinColumn/@MapKeyJoinColumns 如果映射键类型是另一个实体。@AttributeOverride/@AttributeOverrides 当映射键是可嵌入对象时。使用钥匙。作为可嵌入对象属性名称的前缀。如果不使用泛型,也可以使用 @MapKeyClass 来定义键的类型。

By doing some examples I am able to understand that @MapKey is just used to map the key to a property of target entity and this key is used only for fetching records. @MapKeyColumn is used to map the key to a property of target entity and this key is used to save as well as fetching records. Please let me know if this is correct?

通过做一些例子,我能够理解@MapKey 只是用于将键映射到目标实体的属性,而此键仅用于获取记录。@MapKeyColumn 用于将键映射到目标实体的属性,此键用于保存和获取记录。请让我知道这是否正确?

Also please let me know when I need to use @MapKeyJoinColumn/@MapKeyJoinColumns & @MapKeyEnumerated / @MapKeyTemporal

另外请让我知道何时需要使用 @MapKeyJoinColumn/@MapKeyJoinColumns 和 @MapKeyEnumerated / @MapKeyTemporal

Thanks!

谢谢!

采纳答案by Vlad Mihalcea

When you use a Mapyou always need to associate at least two entities. Let's say we have an Ownerentity that relates to the Carentity (Carhas a FK to Owner).

当您使用 a 时,Map您总是需要关联至少两个实体。假设我们有一个与Owner实体相关的Car实体(Car有一个 FK to Owner)。

So, the Ownerwill have a Mapof Car(s):

所以,Owner就有了MapCar(s)

Map<X, Car>

@MapKey

@MapKey

The @MapKeywill give you the Car'sproperty used to group a Carto its Owner. For instance, if we have a vin(Vehicle Identification Number) property in Car, we could use it as the carMapkey:

@MapKey会给你Car's用来集团的物业CarOwner。例如,如果我们在 中有一个vin(Vehicle Identification Number) 属性Car,我们可以将它用作carMap键:

@Entity
public class Owner {
    @Id
    private long id;

    @OneToMany(mappedBy="owner")
    @MapKey(name = "vin")
    private Map<String, Car> carMap;
}

@Entity
public class Car {
    @Id
    private long id;

    @ManyToOne
    private Owner owner;

    private String vin;

}

@MapKeyEnumerated

@MapKeyEnumerated

The @MapKeyEnumeratedwill use an Enum from Car, like WheelDrive:

@MapKeyEnumerated会使用枚举从Car,像WheelDrive

@Entity
public class Owner {
    @Id
    private long id;

    @OneToMany(mappedBy="owner")
    @MapKeyEnumerated(EnumType.STRING)
    private Map<WheelDrive, Car> carMap;
}

@Entity
public class Car {
    @Id
    private long id;

    @ManyToOne
    private Owner owner;

    @Column(name = "wheelDrive")
    @Enumerated(EnumType.STRING)
    private WheelDrive wheelDrive;

}

public enum WheelDrive {
    2WD, 
    4WD;             
}

This will group cars by their WheelDrive type.

这将按其 WheelDrive 类型对汽车进行分组。

@MapKeyTemporal

@MapKeyTemporal

The @MapKeyTemporalwill use a Date/Calendarfield for grouping, like createdOn.

@MapKeyTemporal会使用Date/Calendar场进行分组,像createdOn

@Entity
public class Owner {
    @Id
    private long id;

    @OneToMany(mappedBy="owner")
    @MapKeyTemporal(TemporalType.TIMESTAMP)
    private Map<Date, Car> carMap;
}

@Entity
public class Car {
    @Id
    private long id;

    @ManyToOne
    private Owner owner;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="created_on")
    private Calendar createdOn;         
}

@MapKeyJoinColumn

@MapKeyJoinColumn

The @MapKeyJoinColumnrequires a third entity, like Manufacturerso that you have an association from Ownerto Carand car has also an association to a Manufacturer, so that you can group all Owner'sCarsby Manufacturer:

@MapKeyJoinColumn需要第三个实体,就像Manufacturer让你从这样一个联合体Owner,以Car与汽车也已经关联到Manufacturer,让您可以将所有Owner'sCarsManufacturer

@Entity
public class Owner {
    @Id
    private long id;

    @OneToMany(mappedBy="owner")
    @MapKeyJoinColumn(name="manufacturer_id")
    private Map<Manufacturer, Car> carMap;
}

@Entity
public class Car {
    @Id
    private long id;

    @ManyToOne
    private Owner owner;

    @ManyToOne
    @JoinColumn(name = "manufacturer_id")
    private Manufacturer manufacturer;          
}

@Entity
public class Manufacturer {
    @Id
    private long id;

    private String name;
}

回答by Ryan

Here's a working example of using @MapKey with @OneToMany with a composite @IdClass. It's obviously not the only way to accomplish the objective here, but I felt this was the most maintainable.

这是将@MapKey 与@OneToMany 与复合@IdClass 一起使用的工作示例。这显然不是实现目标的唯一方法,但我觉得这是最容易维护的。

@Entity
@Table(name = "template_categories")
@IdClass(TemplateCategoryId.class)
public class TemplateCategory implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    long orgId;
    @Id
    long templateId;

    @OneToMany(targetEntity = TemplateEntry.class)
    @JoinColumns( {
        @JoinColumn(name = "orgId",  referencedColumnName = "orgId"),
        @JoinColumn(name = "templateId",  referencedColumnName = "templateId")
        }
    )
    @MapKey(name="key")
    private Map<String, TemplateEntry> keyMap;

source code: https://github.com/in-the-keyhole/jpa-entity-map-examples/blob/master/src/main/java/com/example/demo/mapkey/entity/TemplateCategory.java

源代码:https: //github.com/in-the-keyhole/jpa-entity-map-examples/blob/master/src/main/java/com/example/demo/mapkey/entity/TemplateCategory.java