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

如何为无主键但存在唯一索引的表创建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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 17:06:04