JPA中单主键表与复合主键表的一对一关联实现问询
JPA实现单主键表与复合主键表的一对一关联方案
这是个很常见的JPA关联场景,我来一步步给你讲清楚怎么实现:
1. 先完善复合主键类CompositePK
你提供的代码没写完,首先要补全复合主键的字段(复合主键至少包含两个字段,这里假设第二个主键字段是otherKey,你可以根据实际表结构调整),同时JPA要求复合主键类必须实现Serializable,并提供equals、hashCode方法以及必要的构造器:
@Embeddable public class CompositePK implements Serializable { private static final long serialVersionUID = 1L; @Column(name = "myId", insertable=false, updatable=false) private Long myId; // 复合主键的第二个字段,根据你的实际表结构修改字段名和类型 @Column(name = "other_key") private String otherKey; // JPA要求的无参构造器 public CompositePK() {} // 方便实例化的全参构造器 public CompositePK(Long myId, String otherKey) { this.myId = myId; this.otherKey = otherKey; } // 必须实现equals和hashCode,用于JPA识别主键唯一性 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CompositePK that = (CompositePK) o; return Objects.equals(myId, that.myId) && Objects.equals(otherKey, that.otherKey); } @Override public int hashCode() { return Objects.hash(myId, otherKey); } // getter和setter方法 public Long getMyId() { return myId; } public void setMyId(Long myId) { this.myId = myId; } public String getOtherKey() { return otherKey; } public void setOtherKey(String otherKey) { this.otherKey = otherKey; } }
2. 创建TableB实体类并建立与TableA的关联
因为TableB的复合主键已经包含了关联TableA的myId字段,我们直接通过这个字段建立一对一关联,注意要设置insertable=false, updatable=false避免重复操作主键字段:
@Entity @Table(name = "TableB") public class TableB { @EmbeddedId private CompositePK id; // 关联TableA,使用myId作为外键关联TableA的主键 @OneToOne @JoinColumn(name = "myId", referencedColumnName = "myId", insertable=false, updatable=false) private TableA tableA; // 示例其他字段,根据你的表结构添加 @Column(name = "b_description") private String description; // 构造器、getter、setter public TableB() {} public TableB(CompositePK id, TableA tableA, String description) { this.id = id; this.tableA = tableA; this.description = description; } // getter和setter方法 public CompositePK getId() { return id; } public void setId(CompositePK id) { this.id = id; } public TableA getTableA() { return tableA; } public void setTableA(TableA tableA) { this.tableA = tableA; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
3. (可选)在TableA中添加双向关联
如果你需要从TableA直接访问对应的TableB,可以在TableA中添加反向关联,通过mappedBy指定关联关系由TableB维护:
@Entity @Table(name = "TableA") public class TableA { @Id @Column(name = "myId") private Long id; @Column(name = "myName") private String name; @Column(name = "myRegion") private String regionName; // 双向关联,mappedBy表示关联关系由TableB的tableA字段维护 @OneToOne(mappedBy = "tableA") private TableB tableB; // 构造器、getter、setter public TableA() {} public TableA(Long id, String name, String regionName, TableB tableB) { this.id = id; this.name = name; this.regionName = regionName; this.tableB = tableB; } // 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 getRegionName() { return regionName; } public void setRegionName(String regionName) { this.regionName = regionName; } public TableB getTableB() { return tableB; } public void setTableB(TableB tableB) { this.tableB = tableB; } }
关键注意点
- 复合主键类必须实现
Serializable,且equals和hashCode方法是JPA识别主键唯一性的必要条件。 - 因为
myId已经作为复合主键的一部分存在,所以所有涉及该字段的注解都要设置insertable=false, updatable=false,防止JPA尝试重复插入或更新这个字段。 - 双向关联时,
mappedBy的作用是指定关联关系的维护方,避免生成多余的外键字段。
内容的提问来源于stack exchange,提问作者user3016222
相关产品推荐
相关产品推荐

