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

使用Hibernate生成自定义对象标识符(附Stock类相关代码)

实现Hibernate自定义嵌入式标识符(Embeddable ID)的完整指南

看起来你已经迈出了第一步——创建了@Embeddable的StockId类,接下来咱们一步步完成Hibernate自定义嵌入式标识符的实现,确保它能正常工作。

1. 完善StockId类的核心实现

首先,你的StockId类还需要补全两个关键部分:完整的setId方法,以及必须的equals()和hashCode()实现(Hibernate依赖这两个方法识别实体唯一性,实现Serializable接口的类也建议重写这两个方法)。

完善后的StockId代码:

@Embeddable
public class StockId implements Serializable {
    private Long id;

    public StockId() {}

    public StockId(Long id) {
        this.id = id;
    }

    @Column(name = "id", nullable = false)
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    // 基于业务主键字段重写equals和hashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        StockId stockId = (StockId) o;
        return Objects.equals(id, stockId.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

注意:一定要基于业务主键字段(这里就是id)实现equals和hashCode,不要用默认的对象引用判断,否则Hibernate会把同一个数据库记录当成不同的实体。

2. 配置Stock实体类关联嵌入式ID

接下来,在Stock类中用@EmbeddedId注解标记StockId类型的字段,替代普通的@Id字段,同时映射其他数据库字段:

@Entity
@Table(name = "stock")
public class Stock {
    // 使用@EmbeddedId关联自定义标识符类
    @EmbeddedId
    private StockId stockId;

    @Column(name = "stock_code", length = 30)
    private String stockCode;

    @Column(name = "stock_name", length = 100)
    private String stockName;

    // 无参构造器(Hibernate要求必须存在)
    public Stock() {}

    // 带ID的构造器,方便创建实例
    public Stock(StockId stockId) {
        this.stockId = stockId;
    }

    // Getter和Setter方法
    public StockId getStockId() {
        return stockId;
    }

    public void setStockId(StockId stockId) {
        this.stockId = stockId;
    }

    public String getStockCode() {
        return stockCode;
    }

    public void setStockCode(String stockCode) {
        this.stockCode = stockCode;
    }

    public String getStockName() {
        return stockName;
    }

    public void setStockName(String stockName) {
        this.stockName = stockName;
    }
}

3. (可选)为ID配置自动生成策略

如果你的id字段是数据库自动生成的(比如Oracle序列、自增列),可以在StockId的getId()方法上添加@GeneratedValue注解指定生成策略。以Oracle序列为例:

@Column(name = "id", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "stock_seq")
@SequenceGenerator(name = "stock_seq", sequenceName = "STOCK_ID_SEQ", allocationSize = 1)
public Long getId() {
    return this.id;
}

这里的STOCK_ID_SEQ需要是你在Oracle数据库中提前创建的序列。

4. 使用自定义ID的常见操作示例

持久化Stock实例

// 创建ID实例(自动生成ID时无需手动设置id值)
StockId stockId = new StockId();

Stock stock = new Stock(stockId);
stock.setStockCode("AAPL");
stock.setStockName("Apple Inc.");

// 保存到数据库
entityManager.persist(stock);

// 保存后可获取自动生成的ID
Long generatedId = stock.getStockId().getId();

根据ID查询Stock实例

StockId stockId = new StockId(1L); // 指定要查询的id值
Stock stock = entityManager.find(Stock.class, stockId);

关键注意事项

  • StockId必须实现Serializable接口,因为Hibernate需要在分布式场景或缓存中序列化标识符。
  • 确保equals()和hashCode()的实现稳定,用Objects.equals处理null情况(比如自动生成ID的实例在持久化前id为null)。
  • 嵌入式ID天生支持复合主键,只需在StockId中添加对应字段并更新equals和hashCode即可。

内容的提问来源于stack exchange,提问作者kaushik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:00:54