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
Difference between @MapKey, @MapKeyColumn and @MapKeyJoinColumn in JPA and Hibernate
提问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 Map
you always need to associate at least two entities. Let's say we have an Owner
entity that relates to the Car
entity (Car
has a FK to Owner
).
当您使用 a 时,Map
您总是需要关联至少两个实体。假设我们有一个与Owner
实体相关的Car
实体(Car
有一个 FK to Owner
)。
So, the Owner
will have a Map
of Car(s)
:
所以,Owner
就有了Map
的Car(s)
:
Map<X, Car>
@MapKey
@MapKey
The @MapKey
will give you the Car's
property used to group a Car
to its Owner
. For instance, if we have a vin
(Vehicle Identification Number) property in Car
, we could use it as the carMap
key:
该@MapKey
会给你Car's
用来集团的物业Car
其Owner
。例如,如果我们在 中有一个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 @MapKeyEnumerated
will 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 @MapKeyTemporal
will use a Date
/Calendar
field 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 @MapKeyJoinColumn
requires a third entity, like Manufacturer
so that you have an association from Owner
to Car
and car has also an association to a Manufacturer
, so that you can group all Owner's
Cars
by Manufacturer
:
将@MapKeyJoinColumn
需要第三个实体,就像Manufacturer
让你从这样一个联合体Owner
,以Car
与汽车也已经关联到Manufacturer
,让您可以将所有Owner's
Cars
的Manufacturer
:
@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;
源代码:https: //github.com/in-the-keyhole/jpa-entity-map-examples/blob/master/src/main/java/com/example/demo/mapkey/entity/TemplateCategory.java