JPA如何为含复合主键的TEAM表与PKG表配置一对多映射
实现步骤
1. 定义TEAM表对应的复合主键类
复合主键类需要满足JPA规范要求:实现
Serializable接口、重写equals()和hashCode()方法、提供无参构造函数。
import jakarta.persistence.Embeddable; import java.io.Serializable; import java.util.Objects; @Embeddable public class TeamId implements Serializable { private Long id; private Long pkgId; // 无参构造 public TeamId() {} // 全参构造 public TeamId(Long id, Long pkgId) { this.id = id; this.pkgId = pkgId; } // getter和setter public Long getId() {return id;} public void setId(Long id) {this.id = id;} public Long getPkgId() {return pkgId;} public void setPkgId(Long pkgId) {this.pkgId = pkgId;} // 重写equals和hashCode @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TeamId teamId = (TeamId) o; return Objects.equals(id, teamId.id) && Objects.equals(pkgId, teamId.pkgId); } @Override public int hashCode() { return Objects.hash(id, pkgId); } }
2. 实现PKG表对应的实体类(一的一方)
import jakarta.persistence.*; import java.util.List; @Entity @Table(name = "PKG") public class Pkg { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String folder; // 一对多映射,mappedBy指向Team实体中关联Pkg的属性名 @OneToMany(mappedBy = "pkg", cascade = CascadeType.ALL, orphanRemoval = true) private List<Team> teams; // getter、setter、构造函数按需补充 public Long getId() {return id;} public void setId(Long id) {this.id = id;} public String getName() {return name;} public void setName(String name) {this.name = name;} public String getFolder() {return folder;} public void setFolder(String folder) {this.folder = folder;} public List<Team> getTeams() {return teams;} public void setTeams(List<Team> teams) {this.teams = teams;} }
3. 实现TEAM表对应的实体类(多的一方)
核心是通过
@MapsId注解将外键pkg_id映射到复合主键的pkgId字段,避免字段重复映射冲突。
import jakarta.persistence.*; @Entity @Table(name = "TEAM") public class Team { // 注入复合主键 @EmbeddedId private TeamId id; private String name; private Integer filescount; // 关联Pkg实体,映射外键pkg_id,通过@MapsId绑定到复合主键的pkgId属性 @ManyToOne @MapsId("pkgId") @JoinColumn(name = "pkg_id") private Pkg pkg; // getter、setter、构造函数按需补充 public TeamId getId() {return id;} public void setId(TeamId id) {this.id = id;} public String getName() {return name;} public void setName(String name) {this.name = name;} public Integer getFilescount() {return filescount;} public void setFilescount(Integer filescount) {this.filescount = filescount;} public Pkg getPkg() {return pkg;} public void setPkg(Pkg pkg) {this.pkg = pkg;} }
注意事项
- 如果你不想用
@Embeddable+@EmbeddedId的方式,也可以使用@IdClass注解实现复合主键,只需要把TeamId的字段分别放到Team实体上加上@Id注解,然后在Team类上标注@IdClass(TeamId.class)即可,关联映射逻辑不变。 - 保存Team实体时,不需要手动给复合主键的pkgId字段赋值,JPA会自动从关联的Pkg实体的id属性中获取值填充。
- 级联操作和孤儿删除属性可以根据实际业务需求调整,不需要的话可以移除。
- 如果是使用Java EE版本的JPA,将代码中的
jakarta.persistence替换为javax.persistence即可。
内容的提问来源于stack exchange,提问作者sudarshan
相关产品推荐
相关产品推荐

