在JPA结果中映射地图<entity,entity =“”>在此描述符

时间:2018-01-11 19:31:40

标签: java hibernate jpa eclipselink jpa-2.0

我需要映射Java Map,其中键和值都是JPA实体。我在JPA 2书(Pro JPA 2)中读到,这应该使用@OneToMany@ManyToMany注释而不是ElementCollection来完成,因为它们都是JPA实体。

我可以获得@ManyToMany注释,没有问题,没有任何属性或任何东西。但据我了解,这种关系是一对多的。对于任何值实体,只能有一个类的实体来保存地图(我在这里正确理解@OneToMany,因为它与地图有关吗?)。

只需使用@OneToMany注释地图即可:

@OneToMany
private Map<Stage, ScoreCard> scoreCards;

导致此异常:

  

[EL Severe]:2018-01-11   21:11:10.755 - ServerSession(53937593) - 异常[EclipseLink-0]   (Eclipse Persistence Services - 2.7.0.v20170811-d680af5):   org.eclipse.persistence.exceptions.IntegrityException Descriptor

     

例外:

     

异常[EclipseLink-93](Eclipse持久性服务 -   2.7.0.v20170811-d680af5):org.eclipse.persistence.exceptions.DescriptorException异常   说明:此描述符中不存在[SCORECARD]表。   描述:   RelationalDescriptor(fi.ipsc_result_server.domain.ResultData.CompetitorResultData    - &GT; [DatabaseTable(COMPETITORRESULTDATA)])

     

异常[EclipseLink-41](Eclipse持久性服务 -   2.7.0.v20170811-d680af5):org.eclipse.persistence.exceptions.DescriptorException异常   描述:必须为序列定义非只读映射   数字字段。描述:   RelationalDescriptor(fi.ipsc_result_server.domain.ResultData.CompetitorResultData    - &GT; [DatabaseTable(COMPETITORRESULTDATA)])

我已经找到了很多关于Map的JPA注释的例子,但是没有一个会显示如何用实体作为键和值来注释地图。

这两个类都使用@Entity进行注释并具有Id,并且可以保持没有问题,除非在尝试将此Map持久化时,因此问题在于Map的注释。

作为测试,我写了一个有Map的测试类: package fi.ipsc_result_server.domain.ResultData;

@Entity
public class TestClass {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    Long id;

    @OneToMany
    @MapKeyJoinColumn(name="testKey")
    Map<TestKeyClass, TestValueClass> testMap;

[getters and setters]
}
package fi.ipsc_result_server.domain.ResultData;
@Entity
public class TestKeyClass {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    Long id;

[getter and setter for id]
}

package fi.ipsc_result_server.domain.ResultData;

@Entity
public class TestValueClass {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    Long id;

[getter and setter for id]
}

这导致了同样的例外:

  

描述符例外:

     

异常[EclipseLink-93](Eclipse持久性服务 -   2.7.0.v20170811-d680af5):org.eclipse.persistence.exceptions.DescriptorException异常   说明:此表中不存在[TESTVALUECLASS]表   描述。描述:   RelationalDescriptor(fi.ipsc_result_server.domain.ResultData.TestClass    - &GT; [DatabaseTable(识别TestClass)])

     

异常[EclipseLink-41](Eclipse持久性服务 -   2.7.0.v20170811-d680af5):org.eclipse.persistence.exceptions.DescriptorException异常   描述:必须为序列定义非只读映射   数字字段。描述:   RelationalDescriptor(fi.ipsc_result_server.domain.ResultData.TestClass    - &GT; [DatabaseTable(识别TestClass)])

2 个答案:

答案 0 :(得分:0)

Map<Entity,Entity>可与@OneToMany@ManyToMany一起使用。 您只需添加一个额外的注释:

@OneToMany
@MapKeyJoinColumn(name="stage")
private Map<Stage, ScoreCard> scoreCards;

其中name是:

  

地图密钥的外键列的名称。

<强>更新

您需要确保值实体具有对密钥实体的引用:

public clas ScoreCard{

  @ManyToOne
  private Stage stage;
}

答案 1 :(得分:0)

所以我通过添加@MapKeyJoinColumn而不是@JoinColumn到地图上的注释来实现这一点。在我的问题末尾包含的TestClass中,这是有效的,创建了表,并且我可以持久保存TestClass的实例,一旦我保持了TestKeyClass的实例,因为级联显然不包含键值实体:< / p>

@OneToMany(cascade = CascadeType.PERSIST)
@JoinColumn(name="TESTCOLUMN")
Map<TestKeyClass, TestValueClass> testMap;

因此。我不知道为什么会这样,为什么它需要以及为什么@MapKeyJoinColumn不起作用。上面的注释生成一个TESTVALUECLASS表,其中包含“TESTCOLUMN”列(来自@JoinColumn注释)和“testMap_KEY”列。列“TESTCOLUMN”是TestClass的连接列,具有TestClass实体的id(具有映射的类)。 “testMap_KEY”是TestKeyClass实例的id,它作为特定值的键。所以我想由于某些原因,EclipseLink没有生成所需的列而没有@JoinColumn注释。

有一次,我通过阅读一点点刷新了我对JPA的微薄知识,并想到在我当前的项目中我将会很好地掌握JPA。就像以前一样,我总是像JPA的一些方面一样困惑,只是觉得“哦,好吧,什么,它的作用”......哦,好吧!谢谢你的帮助,Maciej!