关键&使用JPA注释映射java.util.Map时,值列名将覆盖 [英] Key & value column name overrides when mapping java.util.Map with JPA annotations

查看:138
本文介绍了关键&使用JPA注释映射java.util.Map时,值列名将覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在看使用Hibernate 4.1.9& JPA注释。

I am looking at the different ways of annotating maps using Hibernate 4.1.9 & JPA annotations.

如果我想存储一个地图,其中的关键是实体值的属性,标记看起来像这样

If I want to store a Map where the key is an attribute of the entity value the mark up looks like this

    @OneToMany(mappedBy = "deptById", targetEntity = com.demo.impls.Employee.class)
    @MapKey(name = "entityId")
    private Map<Long, Employee> employeesById;

请注意,以上标记不会创建连接表,但是通过运行中的查询返回地图时间,所以地图是动态的,你不必在Java中的地图中添加元素,以便它们被查询返回。

Note the above mark up does not create a join table but the Map is returned via a query at run-time, so the Map is dynamic and you do not have to add element into the map in Java for them to be returned by the query.

现在我想要地图的内容来反映应用程序添加到地图中而不是执行动态查询。

Now I want the contents of the Map to reflect what the application has added into the Map rather than performing a dynamic query.

有4种地图我想要存储的地图

There are 4 varieties of Map I want to store

    private Map<String, String> map0;
    private Map<String, Entity> map1;
    private Map<Entity, String> map2;
    private Map<Entity, Entity> map3;

在这些情况下,键&并且价值也不与持有实体有任何关系。
我必须能够指定连接表的名称和密钥&价值。

In these cases there is NO relationship between the key & and value nor is there any relationship to the holding Entity. I have to be able to specify the name of the join table was well as the column names for the key & value.

我尝试了以下

@Entity
public class Department {
    @ElementCollection
    @CollectionTable(name = "TEST_MAP0")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<String, String> map0;

    @ElementCollection(targetClass = com.demo.bb.impls.Employee.class)
    @CollectionTable(name = "TEST_MAP1")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<String, Employee> map1;

    @ElementCollection
    @MapKeyClass(value = com.demo.bb.impls.Employee.class)
    @CollectionTable(name = "TEST_MAP2")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<Employee, String> map2;

    @ElementCollection(targetClass = com.demo.bb.impls.ParkingSpace.class)
    @MapKeyClass(value = com.demo.bb.impls.Employee.class)
    @CollectionTable(name = "TEST_MAP3")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<Employee, ParkingSpace> map3;

案例0地图工作正常生成的连接表具有列DEPARTMENT,VALUE,KEY

Case 0 Map works fine & the generated join table has columns DEPARTMENT, VALUE, KEY

其他三种情况与您可以将数据存储在表&在Java中使用相关的键/值&获取预期的结果 - 即它使用@ElementCollection处理存储实体

The other three cases work in as much as you can store data in the tables & in Java interrogate the tables with the relevant keys/values & get back the expected results - i.e. it does handle storing Entities using @ElementCollection

但是,列名称使用@Column(name =value)&当键或值为实体时,将忽略@MapKeyColumn(name =key)。

But the column name overrides using @Column(name="value") & @MapKeyColumn(name="key") are ignored when the key or value is an Entity.

我已经尝试使用@ManyToMany注释,如下所示

I have tried using @ManyToMany annotations as follows

    @ManyToMany(targetEntity = com.demo.bb.impls.Employee.class)
    @JoinTable(name = "TEST_MAP1_B")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<String, Employee> map1_B;

    @ManyToMany(targetEntity = com.demo.bb.impls.ParkingSpace.class)
    @MapKeyClass(value = com.demo.bb.impls.Employee.class)
    @JoinTable(name = "TEST_MAP3_B")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<Employee, ParkingSpace> map3_B;

但是,值列名覆盖将被忽略。有没有人知道如何强制这些列名覆盖。

But again the key & value column names overrides are ignored. Does anybody know of a way to enforce these column name overrides.

提前感谢...

更新....查看@wypieprz的响应后,我想我知道正确的注释,以允许您指定值&当地图由具有实体价值的基础键入时的关键。

UPDATE....After looking at the response from @wypieprz I think I know the correct annotation to allow you to specify column names for the value & the key when the Map is keyed by a basic with an entity value.

通过使用以下

    @ManyToMany(targetEntity = com.demo.bb.impls.Employee.class)
    @JoinTable(name = "TEST_MAP1", inverseJoinColumns=@JoinColumn(name="VALUE"))
    @MapKeyColumn(name="KEY")
    private Map<String, Employee> map1;

使用inverseJoinColumn可以指定值列名。

Using the inverseJoinColumn I can specify the value column name.

但是如果密钥是实体,我还没有找到一种方法来指定密钥列名称。正如文档所说@MapKeyColumn指定地图关键字是基本类型的地图的关键列的映射

But If the key is an Entity I have not found a way to specify the key column name. As the doc say @MapKeyColumn "specifies the mapping for the key column of a map whose map key is a basic type"

我也不确定注释要使用当关键是实体&价值是一个基本的。使用ManyToMany只是不工作&我想我可能不得不使用ElementCollection,但是再次找不到指定密钥列名称的方法。

I am also not sure of the annotations to use when the key is an Entity & the value is a basic. Using ManyToMany just does not work & I think I may have to use ElementCollection but again I cannot find a way to specify the key column name.

更新2 ...
感谢Peter Halicky解决方案。

UPDATE 2... Thanks to Peter Halicky for a solution.

总而言之,为了命名每个案例的所有3列,您需要执行此类操作。

In summary to name all 3 columns on each of the cases you need to do something like this.

@ElementCollection
@CollectionTable(name = "TEST_MAP0", joinColumns = @JoinColumn(name = "DEPARTMENT"))
@Column(name = "value")
@MapKeyColumn(name = "key")
private Map<String, String> map0;

@ManyToMany(targetEntity = com.hibernate.elephants.Employee.class)
@JoinTable(name = "TEST_MAP1", joinColumns = @JoinColumn(name = "DEPARTMENT"), inverseJoinColumns = @JoinColumn(name = "value"))
@MapKeyColumn(name = "key")
private Map<String, Employee> map1;

@ElementCollection
@CollectionTable(name = "TEST_MAP2", joinColumns = @JoinColumn(name = "DEPARTMENT"))
@MapKeyClass(value = com.hibernate.elephants.Employee.class)
@MapKeyJoinColumn(name = "key")
@Column(name = "value")
private Map<Employee, String> map2;

@ManyToMany(targetEntity = com.hibernate.elephants.ParkingSpace.class)
@JoinTable(name = "TEST_MAP3", joinColumns = @JoinColumn(name = "DEPARTMENT"), inverseJoinColumns = @JoinColumn(name = "value"))
@MapKeyClass(value = com.hibernate.elephants.Employee.class)
@MapKeyJoinColumn(name="key")
private Map<Employee, com.hibernate.elephants.ParkingSpace> map3;

注意两个情况指定为ElementCollection,但两个值是另一个实体需要使用ManyToMany

Note two cases are specified as ElementCollection but the two cases where the value is another Entity need to use ManyToMany.

推荐答案

我正在使用一个实体作为地图的键,如下所示。使用@MapKeyJoinColumn注释,我可以指定作为地图关键字的列的名称。这对于Hibernate来说是有效的,不知道其他的JPA实现会做什么,但肯定值得尝试。

I'm using an entity as a key to a Map, as below. Using the @MapKeyJoinColumn annotation I could specify the name of the column that is the key of the map. This worked for me on Hibernate, not sure what other JPA implementations will do, but it surely is worth trying.

@ElementCollection
@CollectionTable(name="breed_descriptions", joinColumns={ @JoinColumn(name="breed") })
@Column(name="description")
@MapKeyJoinColumn(name="language")
private Map<Language, String> descriptions = new HashMap<>();

这篇关于关键&amp;使用JPA注释映射java.util.Map时,值列名将覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆