JPA和Hibernate中@MapKey,@ MapKeyColumn和@MapKeyJoinColumn的区别

时间:2014-08-22 04:56:27

标签: java hibernate jpa orm hibernate-mapping

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

  

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

     

@MapKeyColumn如果地图键是基本类型。如果你没有指定   列名,后跟下划线的属性名称   使用KEY(例如orders_KEY)。 @MapKeyEnumerated /   @MapKeyTemporal如果map键类型分别是枚举或Date。   @ MapKeyJoinColumn / @ MapKeyJoinColumns如果地图键类型是另一个   实体。当map键是a时,@ AttributeOverride / @ AttributeOverrides   可嵌入的对象。使用密钥。作为可嵌入对象的前缀   财产名称。您还可以使用@MapKeyClass来定义类型   如果你不使用泛型,那就是关键。

通过一些示例,我能够理解@MapKey仅用于将键映射到目标实体的属性,并且此键仅用于获取记录。 @MapKeyColumn用于将键映射到目标实体的属性,该键用于保存和获取记录。如果这是正确的,请告诉我?

当我需要使用@ MapKeyJoinColumn / @ MapKeyJoinColumns&时,请告诉我。 @MapKeyEnumerated / @MapKeyTemporal

谢谢!

2 个答案:

答案 0 :(得分:31)

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

因此,OwnerMap Car(s)

Map<X, Car>

@MapKey

@MapKey会为您提供Car's属性,用于将Car分组到其Owner。例如,如果vin中有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将使用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;             
}

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

@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,以便您拥有从OwnerCar的关联,并且汽车也与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;
}

答案 1 :(得分:0)

这是一个将@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