Hibernate 嵌入式ID映射因描述符异常而失败:应该为主键字段(EclipseLink)定义一个非只读映射

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 =

我有以下非常简单的设计:

一个俱乐部有多个团队,每个团队都有一个团队类型代码(性别-年龄组代码)加上序号(团队编号),例如,20岁以上的男性为“MO20”,序号代表该年龄组的第一、第二等团队。这是
团队的主键。你明白了

俱乐部映射:

@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注释中最令人毛骨悚然的,或者说是文档中的第一句话。