如何为以外键作为主键的area_item_table创建实体类(无需新增主键)
可以无需新增主键字段创建area_item_table的实体类
完全可以通过复合主键的方式实现,不需要新增额外主键字段,下面提供两种常用的实现方案:
方案一:使用@IdClass定义复合主键
1. 定义主键类
这个类需要实现Serializable,且重写equals()和hashCode()方法:
import java.io.Serializable; import java.util.Objects; public class AreaItemId implements Serializable { private Long itemId; // 名称需与AreaItem实体中的对应字段一致 private Long areaId; public AreaItemId() {} public AreaItemId(Long itemId, Long areaId) { this.itemId = itemId; this.areaId = areaId; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AreaItemId that = (AreaItemId) o; return Objects.equals(itemId, that.itemId) && Objects.equals(areaId, that.areaId); } @Override public int hashCode() { return Objects.hash(itemId, areaId); } // getter和setter方法 }
2. 创建area_item_table对应的实体类
import jakarta.persistence.*; @Entity @Table(name = "area_item_table") @IdClass(AreaItemId.class) public class AreaItem { @Id @Column(name = "item_id") private Long itemId; @Id @Column(name = "area_id") private Long areaId; // 关联Item实体 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "item_id", insertable = false, updatable = false) private Item item; // 关联Area实体 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "area_id", insertable = false, updatable = false) private Area area; // getter和setter方法 }
方案二:使用@EmbeddedId定义嵌入式复合主键
1. 定义嵌入式主键类
同样需要实现Serializable:
import jakarta.persistence.Embeddable; import java.io.Serializable; import java.util.Objects; @Embeddable public class AreaItemEmbeddedId implements Serializable { @Column(name = "item_id") private Long itemId; @Column(name = "area_id") private Long areaId; public AreaItemEmbeddedId() {} public AreaItemEmbeddedId(Long itemId, Long areaId) { this.itemId = itemId; this.areaId = areaId; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AreaItemEmbeddedId that = (AreaItemEmbeddedId) o; return Objects.equals(itemId, that.itemId) && Objects.equals(areaId, that.areaId); } @Override public int hashCode() { return Objects.hash(itemId, areaId); } // getter和setter方法 }
2. 创建实体类
使用@EmbeddedId和@MapsId关联对应实体:
import jakarta.persistence.*; @Entity @Table(name = "area_item_table") public class AreaItem { @EmbeddedId private AreaItemEmbeddedId id; @ManyToOne(fetch = FetchType.LAZY) @MapsId("itemId") // 对应AreaItemEmbeddedId中的itemId字段 @JoinColumn(name = "item_id") private Item item; @ManyToOne(fetch = FetchType.LAZY) @MapsId("areaId") // 对应AreaItemEmbeddedId中的areaId字段 @JoinColumn(name = "area_id") private Area area; // getter和setter方法 }
注意事项
- 复合主键类必须实现
Serializable,这是JPA的硬性要求,因为主键需要支持序列化用于缓存、持久化等操作。 - 两种方案均无需新增额外主键字段,直接复用现有
item_id和area_id作为复合主键。 - 若保留原Item实体中的
@OneToOne关联,需注意维护关联关系的一致性,避免出现数据冲突。
内容的提问来源于stack exchange,提问作者kisame
相关产品推荐
相关产品推荐

