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

前端 未结 2 485
[愿得一人]
[愿得一人] 2020-12-04 13:53

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

A

相关标签:
2条回答
  • 2020-12-04 13:53

    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).

    So, the Owner will have a Map of Car(s):

    Map<X, Car>
    

    @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:

    @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

    The @MapKeyEnumerated will use an Enum from Car, like 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.

    @MapKeyTemporal

    The @MapKeyTemporal will use a Date/Calendar field for grouping, like 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

    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:

    @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;
    }
    
    0 讨论(0)
  • 2020-12-04 13:54

    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.

    @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

    0 讨论(0)
提交回复
热议问题