我需要映射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)])
答案 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!