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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 04:27:05