Spring JPA如何将外键关联到目标实体嵌入式主键的指定字段
问题原因
LeagueTeam使用了复合嵌入式主键(由code和name两个字段组成),当你在PlayerBasicInformation中用@ManyToOne关联LeagueTeam时,JPA要求外键必须匹配复合主键的所有列,但你只配置了TEAM_CODE对应code字段,缺少对应name字段的外键列,因此触发了映射异常。
解决方案
根据业务场景,提供两种可行方案:
方案一:调整主键设计(推荐)
观察到LeagueTeamPrimaryKey中的code字段已经标记为unique = true,说明code本身是唯一的,完全可以作为单独的主键,无需使用复合主键。这种方式能简化关联配置,避免复合主键带来的复杂度:
- 修改
LeagueTeam实体类:
@Entity @DynamicUpdate @Table(name = "LEAGUE_TEAM") public class LeagueTeam { @Id @Column(unique = true, updatable = false) private int code; @Column(length = 30, updatable = false) private String name; // 保留原有其他字段 private int draw; private float form; private int loss; private int played; private int points; private int position; @Column(name = "SHRT_NAME", length = 3) private String shortName; @Column(name = "STRGTH") private int strength; @Column(name = "TEAM_DIV", length = 10) private String teamDivision; @Column(name = "UN_AVLBL") private boolean unavailable; private int win; @Column(name = "STRGTH_OVR_HOME") private int strengthOverallHome; @Column(name = "STRGTH_OVR_AWAY") private int strengthOverallAway; @Column(name = "STRGTH_ATT_HOME") private int strengthAttackHome; @Column(name = "STRGTH_ATT_AWAY") private int strengthAttackAway; @Column(name = "STRGTH_DEF_HOME") private int strengthDefenceHome; @Column(name = "STRGTH_DEF_AWAY") private int strengthDefenceAway; @Column(name = "PULSE_ID") private int pulseId; }
删除
LeagueTeamPrimaryKey类,无需再使用嵌入式主键。PlayerBasicInformation的关联配置保持不变即可正常工作:
@ManyToOne(optional = false) @JoinColumn(name = "TEAM_CODE", referencedColumnName = "CODE") private LeagueTeam teamCode;
方案二:保留复合主键,添加完整外键列
如果业务上必须保留复合主键,那么需要在PlayerBasicInformation的数据库表中添加对应name字段的外键列,并配置完整的关联映射:
修改PlayerBasicInformation实体类:
@Entity @Table(name = "PLYR_BSC_INFO") public class PlayerBasicInformation { @Id private Long code; @Column(name = "FRST_NAME") private String firstName; @Column(name = "SECD_NAME") private String secondName; @Column(name = "SQD_NO") private Integer squadNumber; @Column(name = "PLYR_STS") private Character status; // 配置对应复合主键的两个外键列 @ManyToOne(optional = false) @JoinColumns({ @JoinColumn(name = "TEAM_CODE", referencedColumnName = "CODE"), @JoinColumn(name = "TEAM_NAME", referencedColumnName = "NAME") }) private LeagueTeam team; @Column(name = "WEB_NAME") private String webName; }
同时需要确保数据库表PLYR_BSC_INFO存在TEAM_NAME列,与LEAGUE_TEAM表的NAME列类型匹配。
内容的提问来源于stack exchange,提问作者Rohan Aditeya
相关产品推荐
相关产品推荐

