使用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
相关产品推荐
相关产品推荐

