Hibernate 嵌入式ID映射因描述符异常而失败:应该为主键字段(EclipseLink)定义一个非只读映射
我有以下非常简单的设计: 一个俱乐部有多个团队,每个团队都有一个团队类型代码(性别-年龄组代码)加上序号(团队编号),例如,20岁以上的男性为“MO20”,序号代表该年龄组的第一、第二等团队。这是Hibernate 嵌入式ID映射因描述符异常而失败:应该为主键字段(EclipseLink)定义一个非只读映射,hibernate,jpa,eclipselink,jpa-2.0,Hibernate,Jpa,Eclipselink,Jpa 2.0,我有以下非常简单的设计: 一个俱乐部有多个团队,每个团队都有一个团队类型代码(性别-年龄组代码)加上序号(团队编号),例如,20岁以上的男性为“MO20”,序号代表该年龄组的第一、第二等团队。这是团队的主键。你明白了 俱乐部映射: @Entity @Table(name = "Clubs") public class Club implements Serializable { private static final long serialVersionUID =
团队的主键。你明白了
俱乐部映射:
@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抱怨团队的列映射。俱乐部id
:
There should be one non-read-only mapping defined for the primary key field [Teams.club_id].
但是为什么呢
嵌入式ID字段,或者更确切地说,ID类在clubId
字段上有@Column
,没有insertable=true,updateable=true
,因此它默认为可写,至少文档是这么说的:
因此,所有其他club\u id
映射必须是insertable=true,updateable=true
只读的,就像Team.club
关系一样
问题:
这里怎么了
请注意,在Team.club
和TeamPk.clubId
之间切换insertable=…,updateable=…
时,整个过程都是有效的
为什么日食在这里窒息?在我看来像个虫子
附言:我正在使用EclipseLink 2.7.7。(hibernate
tag的添加只是为了吸引更多的注意力)通过将@MapsId(“clubId”)
放在关联上,可以说“clubId
不提供自己的映射。相反,应该使用此属性上的映射来映射clubId
属性”
这意味着在持久化实体时,Eclipselink将使用Team.club
的id填充club\u id
连接列,然后,每当获取/刷新实体时,它将使用该连接列的值填充Java属性Team.embeddedId.clubbid
您在Team.embeddedId.clubId上放置的任何映射都将被忽略
这个错误来自于Eclipse没有考虑“代码> CulbSIDID/CODE >两次映射的事实。相反,只考虑
Team.club
上的映射。作为主键属性的唯一映射,它可能不是insertable=false,updateable=false
解决方案很简单:
如果希望Team.club
控制club\u id
列的值,请删除insertable=false,updateable=false
相反,如果希望Team.embeddedId.clubId
控制club\u id
,请将@MapsId
一起删除
您描述的行为是JPA规范定义的还是EclipseLink所做的,例如历史上的?我在文档中的任何地方都找不到@MapsId
以这种方式运行,请参阅。文档通常直接从规范中摘取句子。这一条(虽然你可能仍然是对的)没有提到任何类似于你所描述的内容。“指定一个manytone或OneToOne关系属性,为(…)EmbeddedId主键中的属性提供映射”是我在回答的第一段中描述的字面意思。我真的理解这一点正好相反:“@MapsId(“clubId”)
告诉映射程序将此关系映射到嵌入ID的clubId
“。与可写性/只读性无关。就在专栏里。从那以后,我在@MapsId
方面遇到了麻烦。也许你是对的,就照你写的那样接受吧@MapsId
是所有JPA注释中最令人毛骨悚然的,或者说是文档中的第一句话。