如何解决嵌入式ID映射失败,出现DescriptorException:应为主键字段EclipseLink定义一个非只读映射
我有以下非常简单的设计:
一个俱乐部有多支球队,每支球队都有球队类型代码(性别-年龄段代码)加上一个序号(球队),例如大于20的男性为“ MO20”,其序号代表该年龄组的第一,第二等团队。这是Teams
的PK。你明白了。
俱乐部映射:
@Entity
@Table(name = "Clubs")
public class Club implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column
private Integer id;
@Basic(optional = false)
@Column
private String name;
@Basic(optional = false)
@Column
private String code;
@OneToMany(mappedBy = "club")
private List<Team> teams;
...
}
团队映射:
@Entity
@Table(name = "Teams")
public class Team implements Serializable
{
private static final long serialVersionUID = 1L;
@EmbeddedId
private TeamPk embeddedId;
@MapsId("clubId")
@ManyToOne(optional = false,fetch = FetchType.EAGER)
@JoinColumn(name = "club_id",insertable = false,updatable = false)
private Club club;
...
}
@Embeddable
public class TeamPk implements Serializable
{
private static final long serialVersionUID = 1L;
@Column(name = "club_id")
private Integer clubId;
@Column(name = "team_type_code")
private String teamTypeCode;
@Column(name = "ordinal_nbr")
private Integer ordinalNbr;
...
}
例外:
Caused by: Exception [EclipseLink-28019] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Deployment of PersistenceUnit [BBStatsPU] failed. Close all factories for this PersistenceUnit.
Internal Exception: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.IntegrityException
Descriptor Exceptions:
---------------------------------------------------------
Exception [EclipseLink-46] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: There should be one non-read-only mapping defined for the primary key field [Teams.club_id].
Descriptor: RelationalDescriptor(net.bbstatstest.i265.entity.Team --> [DatabaseTable(Teams)])
Runtime Exceptions:
---------------------------------------------------------
at org.eclipse.persistence.exceptions.EntityManagerSetupException.deployFailed(EntityManagerSetupException.java:241)
... 182 more
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.IntegrityException
Descriptor Exceptions:
---------------------------------------------------------
Exception [EclipseLink-46] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: There should be one non-read-only mapping defined for the primary key field [Teams.club_id].
Descriptor: RelationalDescriptor(net.bbstatstest.i265.entity.Team --> [DatabaseTable(Teams)])
Runtime Exceptions:
---------------------------------------------------------
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:762)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:698)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:629)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:868)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:811)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:256)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:772)
... 180 more
EclipseLink抱怨Teams.club_id
的列映射:
There should be one non-read-only mapping defined for the primary key field [Teams.club_id].
但是为什么?
嵌入的ID字段或更确切的ID类在@Column
字段上具有clubId
,而没有insertable = true,updatable = true
,因此它默认为可写的,至少文档是这样说的: https://javaee.github.io/javaee-spec/javadocs/javax/persistence/Column.html#insertable--
因此,所有其他club_id
映射必须为insertable = true,updatable = true
才能是只读的,就像Team.club
关系一样。
问题:
这是怎么了?
请注意,当在insertable = ...,updatable = ...
和Team.club
之间切换TeamPk.clubId
时,整个过程都起作用。
为什么EclipseLink在这里令人窒息?对我来说似乎是个虫子。
PS:我正在使用EclipseLink 2.7.7。 (仅添加hibernate
标签以引起更多关注)
解决方法
通过将@MapsId("clubId")
放在关联上,您是说'clubId
不会不提供其自己的映射。相反,应使用此处对此属性的映射来映射clubId
属性'。
这意味着在持久化实体时,Eclipselink将使用Team.club
的ID填充club_id
连接列,然后,将使用该连接列的值填充 Java属性 Team.embeddedId.clubId
。 您放置在Team.embeddedId.clubId
上的任何映射都将被忽略。
该错误来自Eclipselink认为club_id
不被映射两次的事实。相反,仅考虑Team.club
上的映射。作为主键属性的唯一映射,它可能不是insertable = false,updatable = false
。
解决方案很简单:
- 如果要
Team.club
控制club_id
列的值,请放下insertable = false,updatable = false
- 相反,如果您希望
Team.embeddedId.clubId
控制club_id
,请完全放下@MapsId
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。