嵌入式 ID 映射失败并出现 DescriptorException:应该为主键字段定义一个非只读映射 (EclipseLink)
Embedded ID mapping fails with DescriptorException: There should be one non-read-only mapping defined for the primary key field (EclipseLink)
我有以下非常简单的设计:
一个俱乐部有多个团队,每个团队都有一个团队类型代码(性别 - 年龄组代码)加上一个序号(团队),例如20 岁以上的男性将是“MO20”,序号代表该年龄组的第 1、2 等队。这是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 class 在 clubId
字段上有 @Column
而没有 insertable = true, updatable = true
,因此它默认为可写,至少这就是文档所说的:https://javaee.github.io/javaee-spec/javadocs/javax/persistence/Column.html#insertable--
因此所有其他 club_id
映射必须是 insertable = true, updatable = true
才能只读,就像 Team.club
关系一样。
问题:
这是怎么回事?
请注意,当在 Team.club
和 TeamPk.clubId
之间切换 insertable = ..., updatable = ...
时,整个事情都有效。
为什么 EclipseLink 卡在这里?在我看来像是一个错误。
PS:我正在使用 EclipseLink 2.7.7。 (hibernate
标签只是为了吸引更多关注而添加的)
通过将 @MapsId("clubId")
放在关联上,您是在说'clubId
不 提供自己的映射。相反,这里 属性 上的映射应该用来映射 clubId
属性'.
这意味着当持久化实体时,Eclipselink 将使用 Team.club
的 id 来填充 club_id
连接列,然后,它将使用该连接列的值来填充Java 属性 Team.embeddedId.clubId
,只要实体是 fetched/refreshed。 您在 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
我有以下非常简单的设计:
一个俱乐部有多个团队,每个团队都有一个团队类型代码(性别 - 年龄组代码)加上一个序号(团队),例如20 岁以上的男性将是“MO20”,序号代表该年龄组的第 1、2 等队。这是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 class 在 clubId
字段上有 @Column
而没有 insertable = true, updatable = true
,因此它默认为可写,至少这就是文档所说的:https://javaee.github.io/javaee-spec/javadocs/javax/persistence/Column.html#insertable--
因此所有其他 club_id
映射必须是 insertable = true, updatable = true
才能只读,就像 Team.club
关系一样。
问题:
这是怎么回事?
请注意,当在 Team.club
和 TeamPk.clubId
之间切换 insertable = ..., updatable = ...
时,整个事情都有效。
为什么 EclipseLink 卡在这里?在我看来像是一个错误。
PS:我正在使用 EclipseLink 2.7.7。 (hibernate
标签只是为了吸引更多关注而添加的)
通过将 @MapsId("clubId")
放在关联上,您是在说'clubId
不 提供自己的映射。相反,这里 属性 上的映射应该用来映射 clubId
属性'.
这意味着当持久化实体时,Eclipselink 将使用 Team.club
的 id 来填充 club_id
连接列,然后,它将使用该连接列的值来填充Java 属性 Team.embeddedId.clubId
,只要实体是 fetched/refreshed。 您在 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