You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring中EmbeddedId关联Race与PersonRace的Join方式问题

问题:Spring JPA构建Race与PersonRace关联时抛出表不存在错误

在数据库中,person_race和race是核心表,使用Spring JPA构建关联关系时,调用findAll接口抛出错误:

Caused by: org.postgresql.util.PSQLException: ERROR: relation "race_person_races" does not exist

相关实体类代码如下:

PersonRace.java

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class PersonRace {

    @EmbeddedId
    @NotNull
    private PersonRaceId personRaceId;

    @Column(name = "player_class")
    @NotNull
    private String playerClass;

    @Column(name = "motorbike_model")
    @NotNull
    private String motorbikeModel;

    @NotNull
    private boolean confirmed;

    @NotNull
    @Column(name = "number_in_race")
    private long numberInRace;
}

PersonRaceId.java

@Embeddable
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class PersonRaceId implements Serializable {

        @OneToOne
        @JoinColumn(name = "race_id")
        @NotNull
        private Race race;
        @OneToOne
        @NotNull
        @JoinColumn(name = "person_id")
        private Person person;
}

Race.java

@Entity
@NoArgsConstructor
@Getter
@Setter
@ToString
public class Race {
    @Id
    @Column(name = "race_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @NotNull
    private Long id;
    @Column(name = "max_players")
    @NotNull
    private Integer maxPlayers;
    @NotNull
    private String description;
    @NotNull
    private String location;
    @NotNull
    private LocalDateTime date;
    @NotNull
    private String state;
    @ManyToOne
    @NotNull
    @JoinColumn(name = "event_id")
    private RaceEvent raceEvent;
    @OneToMany
    @JoinColumn(name = "lap_id")
    private List<Lap> laps;
    @OneToMany
    // 问题代码
    @PrimaryKeyJoinColumns(value = {
            @PrimaryKeyJoinColumn(name = "race_id", referencedColumnName = "race_id"),
            @PrimaryKeyJoinColumn(name = "person_id", referencedColumnName = "person_id")
    })
    private List<PersonRace> personRaces;

    public Race(@NotNull Long id, @NotNull Integer maxPlayers, @NotNull String description, @NotNull String location, @NotNull LocalDateTime date, @NotNull String state, @NotNull RaceEvent raceEvent, List<Lap> laps, List<PersonRace> personRaces) {
        this.id = id;
        this.maxPlayers = maxPlayers;
        this.description = description;
        this.location = location;
        this.date = date;
        this.state = state;
        this.raceEvent = raceEvent;
        this.laps = laps;
        this.personRaces = personRaces;
    }
}

解决方案

1. 修正复合主键中的映射方式

复合主键类PersonRaceId不能直接用实体关联注解,需改用基本类型映射数据库主键字段:

@Embeddable
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class PersonRaceId implements Serializable {

    @Column(name = "race_id")
    @NotNull
    private Long raceId;

    @Column(name = "person_id")
    @NotNull
    private Long personId;
}

2. 在PersonRace中建立与Race、Person的关联

通过@MapsId注解将实体关联映射到复合主键的对应字段:

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class PersonRace {

    @EmbeddedId
    @NotNull
    private PersonRaceId personRaceId;

    @ManyToOne
    @MapsId("raceId") // 关联复合主键中的raceId字段
    @JoinColumn(name = "race_id")
    @NotNull
    private Race race;

    @ManyToOne
    @MapsId("personId") // 关联复合主键中的personId字段
    @JoinColumn(name = "person_id")
    @NotNull
    private Person person;

    @Column(name = "player_class")
    @NotNull
    private String playerClass;

    @Column(name = "motorbike_model")
    @NotNull
    private String motorbikeModel;

    @NotNull
    private boolean confirmed;

    @NotNull
    @Column(name = "number_in_race")
    private long numberInRace;
}

3. 修正Race中的@OneToMany关联

使用mappedBy指定关联关系由PersonRace中的race字段维护,避免JPA生成不存在的中间表:

@OneToMany(mappedBy = "race", fetch = FetchType.LAZY)
private List<PersonRace> personRaces;

错误原因说明

  • 原代码中PersonRaceId直接用@OneToOne关联实体,违反JPA复合主键规范,复合主键应使用基本数据类型映射数据库字段。
  • Race中误用@PrimaryKeyJoinColumns,导致JPA错误认为需要生成中间表race_person_races,实际person_race本身就是关联表,需通过mappedBy指定反向关联。

内容的提问来源于stack exchange,提问作者Ser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:01:34