java - 使用 JPA 注释映射 java.util.Map 时,键和值列名称会被覆盖

标签 java hibernate jpa dictionary annotations

我正在研究使用 Hibernate 4.1.9 和 JPA 注释对 map 进行注释的不同方式。

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

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

请注意,上面的标记不会创建连接表,但 Map 是在运行时通过查询返回的,因此 Map 是动态的,您不必在 Java 中将元素添加到 map 中即可返回通过查询。

现在我希望 Map 的内容反射(reflect)应用程序添加到 Map 中的内容,而不是执行动态查询。

我要存储4种Map

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

在这些情况下,键和值之间没有任何关系,与控股实体也没有任何关系。 我必须能够指定连接表的名称以及键和值的列名。

我试过以下方法

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

Case 0 Map 工作正常,生成的连接表有 DEPARTMENT、VALUE、KEY 列

其他三种情况的工作方式与您可以将数据存储在表中一样多,并且在 Java 中使用相关键/值查询表并返回预期结果 - 即它确实使用 @ElementCollection 处理存储实体

但当键或值是实体时,使用@Column(name="value") 和@MapKeyColumn(name="key") 的列名称覆盖将被忽略。

我试过如下使用@ManyToMany注解

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

但是再次忽略键和值列名覆盖。有谁知道强制执行这些列名称覆盖的方法。

提前致谢...

更新....在查看来自@wypieprz 的回复后,我想我知道正确的注释,允许您在 Map 由具有实体值的基本键控时为值和键指定列名。

通过使用以下内容

    @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 我可以指定值列名称。

但是如果键是一个实体,我还没有找到指定键列名称的方法。正如文档所说@MapKeyColumn“指定映射键列的映射,其映射键是基本类型”

我也不确定当键是实体而值是基本时要使用的注释。使用 ManyToMany 是行不通的,我想我可能不得不使用 ElementCollection,但我还是找不到指定键列名称的方法。

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

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

@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,但值是另一个 Entity 的两种情况需要使用 ManyToMany。

最佳答案

我正在使用实体作为 map 的键,如下所示。使用 @MapKeyJoinColumn 注释我可以指定作为 map 键的列的名称。这对我在 Hibernate 上有用,不确定其他 JPA 实现会做什么,但它肯定值得尝试。

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

关于java - 使用 JPA 注释映射 java.util.Map 时,键和值列名称会被覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24138694/

相关文章:

java - 无法使用 Selenium 网格中的 maxSession 将浏览器 session 限制为 1 (Java)

java - JPA 继承 : Mapped Superclass vs Table Per Class

java - JPA CreateNativeQuery 返回错误的日期

java - JPA 以及与持久性提供程序和数据库供应商的兼容性

java - JAXB Moxy 混合空格丢失

java - Android6.0 WebView显示空白页

java - 获取单个 ScrollableResults 行

hibernate - 如何使用 spring boot 1.5.x 配置 "hibernate.integrator_provider"

java - 数据 JPA - 从存储库中删除实体

java - 如何查询 blob?