如何为无主键但存在唯一索引的表创建JPA模型类
无主键带联合唯一索引的JPA实体类编写方案
JPA规范要求所有实体类必须声明主键,对于没有单独主键字段、但存在稳定联合唯一索引的表,可以将组成唯一索引的多个字段封装为复合主键使用,针对你给出的popular_item表场景,具体实现步骤如下:
1. 定义复合主键类
复合主键类需要满足三个要求:实现Serializable接口、重写equals和hashCode方法、提供无参构造方法。
import java.io.Serializable; import java.util.Objects; public class PopularItemId implements Serializable { // 四个字段对应联合唯一索引的组成部分 private Long itemEntityId; private Integer itemType; private String itCode; private Integer quantity; // 无参构造 public PopularItemId() {} // 全参构造(方便构造主键查询) public PopularItemId(Long itemEntityId, Integer itemType, String itCode, Integer quantity) { this.itemEntityId = itemEntityId; this.itemType = itemType; this.itCode = itCode; this.quantity = quantity; } // getter和setter public Long getItemEntityId() {return itemEntityId;} public void setItemEntityId(Long itemEntityId) {this.itemEntityId = itemEntityId;} public Integer getItemType() {return itemType;} public void setItemType(Integer itemType) {this.itemType = itemType;} public String getItCode() {return itCode;} public void setItCode(String itCode) {this.itCode = itCode;} public Integer getQuantity() {return quantity;} public void setQuantity(Integer quantity) {this.quantity = quantity;} // 重写equals和hashCode @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PopularItemId that = (PopularItemId) o; return Objects.equals(itemEntityId, that.itemEntityId) && Objects.equals(itemType, that.itemType) && Objects.equals(itCode, that.itCode) && Objects.equals(quantity, that.quantity); } @Override public int hashCode() { return Objects.hash(itemEntityId, itemType, itCode, quantity); } }
2. 编写主实体类
使用@IdClass注解绑定上面定义的复合主键类,四个联合索引字段都添加@Id注解标识为主键组成部分,其余字段按普通字段映射即可。
import jakarta.persistence.*; import java.util.Date; @Entity @Table(name = "popular_item", uniqueConstraints = {@UniqueConstraint(columnNames = {"item_entity_id", "item_type", "it_code", "quantity"})} ) @IdClass(PopularItemId.class) public class PopularItem { @Id @Column(name = "item_entity_id", nullable = false) private Long itemEntityId; @Id @Column(name = "item_type", nullable = false) private Integer itemType; @Id @Column(name = "it_code", nullable = false) private String itCode; @Id @Column(name = "quantity", nullable = false) private Integer quantity; @Column(name = "status") private Integer status; @Column(name = "created_date") @Temporal(TemporalType.TIMESTAMP) private Date createdDate; // 无参构造、全参构造、getter、setter按需补充 public PopularItem() {} // 此处省略getter和setter方法,实际开发需要补充 }
补充说明
- 后续调用
JpaRepository的findById方法时,直接构造PopularItemId对象作为参数即可完成主键查询 - 如果你用的JPA实现是Hibernate,也可以选择
@EmbeddedId的方式实现复合主键,两种方式功能一致,@IdClass的写法更适合不需要单独把主键类作为参数传递的场景 - 类上
@Table的uniqueConstraints配置是可选的,仅用于JPA自动生成表结构时对齐索引配置,如果你不需要JPA自动建表可以省略
内容的提问来源于stack exchange,提问作者Euphoria
相关产品推荐
相关产品推荐

