JPA和Hibernate中@MapKey、@MapKeyColumn和@MapKeyJoinColumn的区别
Posted
技术标签:
【中文标题】JPA和Hibernate中@MapKey、@MapKeyColumn和@MapKeyJoinColumn的区别【英文标题】:Difference between @MapKey, @MapKeyColumn and @MapKeyJoinColumn in JPA and Hibernate 【发布时间】:2014-10-15 21:10:54 【问题描述】:根据Hibernate documentation,如果我们想使用 Map 作为实体之间的关联,可以使用多个注释。医生说:
或者,映射键被映射到一个或多个专用列。 为了自定义映射使用以下之一 注释:
@MapKeyColumn 如果映射键是基本类型。如果您不指定 列名,属性名后跟下划线 通过 KEY 使用(例如 orders_KEY)。 @MapKeyEnumerated / @MapKeyTemporal 如果映射键类型分别是枚举或日期。 @MapKeyJoinColumn/@MapKeyJoinColumns 如果映射键类型是另一个 实体。 @AttributeOverride/@AttributeOverrides 当映射键是 可嵌入对象。使用钥匙。作为可嵌入对象的前缀 属性名称。也可以使用@MapKeyClass 来定义类型 如果您不使用泛型,则为关键。
通过一些示例,我可以理解@MapKey 仅用于将键映射到目标实体的属性,并且该键仅用于获取记录。 @MapKeyColumn 用于将键映射到目标实体的属性,该键用于保存和获取记录。请告诉我这是否正确?
当我需要使用@MapKeyJoinColumn/@MapKeyJoinColumns & @MapKeyEnumerated / @MapKeyTemporal 时请告诉我
谢谢!
【问题讨论】:
【参考方案1】:这是一个将@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
【讨论】:
【参考方案2】:当您使用Map
时,您始终需要关联至少两个实体。假设我们有一个与Car
实体相关的Owner
实体(Car
与Owner
有一个FK)。
所以,Owner
将有一个 Map
或 Car(s)
:
Map<X, Car>
@MapKey
@MapKey
将为您提供Car's
属性,用于将Car
分组到其Owner
。例如,如果我们在Car
中有一个vin
(车辆识别号)属性,我们可以将其用作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
将使用来自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;
这将按照车轮驱动类型对汽车进行分组。
@MapKeyTemporal
@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
需要第三个实体,例如 Manufacturer
,以便您拥有从 Owner
到 Car
的关联,并且 car 还具有与 Manufacturer
的关联,这样您就可以对所有 @987654358 进行分组@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;
【讨论】:
嗨,弗拉德,如果可能的话,请您看看我的另一篇帖子 - ***.com/questions/25664452/… 非常感谢您的支持。 今晚我去看看 我也有类似的问题。出于某种原因,@MapKey
没有给我预期的结果。你也可以看看这个:***.com/questions/31235462/… 吗? ^^
@VladMihalcea 目前我正在从hibernate 3.3.2
迁移到hibernate 4.3.11
。如何迁移@MapKey
导致MapKey无法解析为hiberante4
中的类型
我在度假。我回来看看。以上是关于JPA和Hibernate中@MapKey、@MapKeyColumn和@MapKeyJoinColumn的区别的主要内容,如果未能解决你的问题,请参考以下文章
JPASpringData JPA Hibernate和Mybatis 的区别和联系