0

我有以下简单的设计:

在此处输入图像描述

球员统计数据是每个球员的统计数据,它为球员保存整场比赛的状态,例如球衣号码。

它引用了一个团队成员,该成员由特定名单中的球员识别(基本上,一个球员可以是多个名单的一部分,例如在一个赛季中为多个球队效力的球员)。

球员统计数据与比赛的得分相关,无论是主场还是客场得分。它基本上是一个带有附加属性/列的连接表。你明白了。

因此,表所引用的两个PlayerStats表都有一个复合 PK。我使用派生标识符映射PlayerStat实体,见下文。

评分实体+ID类(无特殊):

@Entity
@Table(name = "Scores")
@IdClass(ScoreId.class)
public class Score implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "game_id")
    private Integer gameId;

    @Id
    @Column(name = "is_home")
    private Boolean home;

    @Basic
    @Column(name = "final_score")
    private Integer finalScore;

    @OneToMany(mappedBy = "score")
    private List<PlayerStat> playerStats;

    ...
}

public class ScoreId implements Serializable
{
    private static final long serialVersionUID = 1L;

    private Integer gameId;

    private Boolean home;

    ...
}

团队成员实体+ID类(无特殊):

@Entity
@Table(name = "TeamMembers")
@IdClass(TeamMemberId.class)
public class TeamMember implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "player_id")
    private Integer playerId;

    @Id
    @Column(name = "roster_id")
    private Integer rosterId;

    @OneToMany(mappedBy = "teamMember")
    private List<PlayerStat> playerStats;

    ...    
}

public class TeamMemberId implements Serializable
{
    private static final long serialVersionUID = 1L;

    private Integer playerId;

    private Integer rosterId;
    
    ...
}

玩家统计实体 + ID 类(派生标识符):

@Entity
@Table(name = "PlayerStats")
@IdClass(PlayerStatId.class)
public class PlayerStat implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Basic(optional = false)
    @Column(name = "jersey_nbr")
    private Integer jerseyNbr;

    @Id
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @JoinColumn(name = "game_id", referencedColumnName = "game_id")
    @JoinColumn(name = "is_home", referencedColumnName = "is_home")
    private Score score;

    @Id
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @JoinColumn(name = "player_id", referencedColumnName = "player_id")
    @JoinColumn(name = "roster_id", referencedColumnName = "roster_id")
    private TeamMember teamMember;
    
    ...
}

public class PlayerStatId implements Serializable
{
    private static final long serialVersionUID = 1L;

    private ScoreId score;

    private TeamMemberId teamMember;

    public PlayerStatId()
    {
    }

    public ScoreId getScoreId()
    {
        return score;
    }

    public void setScoreId(ScoreId scoreId)
    {
        this.score = scoreId;
    }

    public TeamMemberId getTeamMemberId()
    {
        return teamMember;
    }

    public void setTeamMemberId(TeamMemberId teamMemberId)
    {
        this.teamMember = teamMemberId;
    }
    
    ...
}

例外:

11:44:27,315 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 78) MSC000001: Failed to start service jboss.persistenceunit."bbstatstest-1.0.war#BBStatsPU": org.jboss.msc.service.StartException in service jboss.persistenceunit."bbstatstest-1.0.war#BBStatsPU": javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [BBStatsPU] failed.
Internal Exception: Exception [EclipseLink-7150] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [net.bbstats.entity.PlayerStatId] and those of the entity bean class [class net.bbstats.entity.PlayerStat] must correspond and their types must be the same. Also, ensure that you have specified ID elements for the corresponding attributes in XML and/or an @Id on the corresponding fields or properties of the entity class.
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:198)
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:128)
    at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:658)
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:212)
    at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1348)
    at java.lang.Thread.run(Thread.java:748)
    at org.jboss.threads.JBossThread.run(JBossThread.java:485)
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [BBStatsPU] failed.
Internal Exception: Exception [EclipseLink-7150] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [net.bbstats.entity.PlayerStatId] and those of the entity bean class [class net.bbstats.entity.PlayerStat] must correspond and their types must be the same. Also, ensure that you have specified ID elements for the corresponding attributes in XML and/or an @Id on the corresponding fields or properties of the entity class.
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.createPredeployFailedPersistenceException(EntityManagerSetupImpl.java:2109)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:2085)
    at org.eclipse.persistence.jpa.PersistenceProvider.createContainerEntityManagerFactoryImpl(PersistenceProvider.java:350)
    at org.eclipse.persistence.jpa.PersistenceProvider.createContainerEntityManagerFactory(PersistenceProvider.java:316)
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.createContainerEntityManagerFactory(PersistenceUnitServiceImpl.java:365)
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.access$1300(PersistenceUnitServiceImpl.java:71)
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:190)
    ... 9 more
Caused by: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [BBStatsPU] failed.
Internal Exception: Exception [EclipseLink-7150] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [net.bbstats.entity.PlayerStatId] and those of the entity bean class [class net.bbstats.entity.PlayerStat] must correspond and their types must be the same. Also, ensure that you have specified ID elements for the corresponding attributes in XML and/or an @Id on the corresponding fields or properties of the entity class.
    at org.eclipse.persistence.exceptions.EntityManagerSetupException.predeployFailed(EntityManagerSetupException.java:233)
    ... 16 more
Caused by: Exception [EclipseLink-7150] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [net.bbstats.entity.PlayerStatId] and those of the entity bean class [class net.bbstats.entity.PlayerStat] must correspond and their types must be the same. Also, ensure that you have specified ID elements for the corresponding attributes in XML and/or an @Id on the corresponding fields or properties of the entity class.
    at org.eclipse.persistence.exceptions.ValidationException.invalidCompositePKSpecification(ValidationException.java:1198)
    at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.validatePrimaryKey(EntityAccessor.java:1531)
    at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.processMappingAccessors(EntityAccessor.java:1251)
    at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.process(EntityAccessor.java:701)
    at org.eclipse.persistence.internal.jpa.metadata.MetadataProject.processStage2(MetadataProject.java:1879)
    at org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor.processORMMetadata(MetadataProcessor.java:580)
    at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processORMetadata(PersistenceUnitProcessor.java:629)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:2006)
    ... 14 more

问题

映射有什么问题?

PlayerStat实体有两个关系scoreteamMember并且各自@IdClass被调用PlayerStatId有两个嵌套的复合 PK类引用,根据需要调用scoreteamMember,它们的类型是各自的 PK 类ScoreIdTeamMemberId

我在 WildFly 20 环境中使用最新的 EclipseLink 2.7.7。

这可能是某种错误吗?

我查看了几个描述派生标识符的来源,但我没有看到映射存在任何固有的错误。

4

2 回答 2

0

映射绝对正确且有效。我有另一个测试应用程序仍然部署在服务器上,具有相同的包/类名,所以错误来自另一个应用程序。对困惑感到抱歉。问题可以完全删除。

于 2020-10-30T14:03:25.483 回答
0

当复合 id 的部分也是复合 id 时,我认为你不能做复合 id。属性的类型也需要匹配:Integer gameId匹配,但ScoreId score不一样Score score

您可能可以通过取消嵌套 id 类并摆弄JoinColumn定义来做到这一点,或者您将不得不硬着头皮为您的实体提供人工主键。

于 2020-10-30T12:50:21.437 回答