實體 E 包含 id(自增)、name(表單輸入)、code1(需在保存時自動生成)。希望在 session.save(e) 時自動填充 code1,不在表單/Controller 處理。
實現 org.hibernate.Interceptor 接口,重寫 onSave 方法:
public class CodeGeneratorInterceptor extends EmptyInterceptor {
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
if (entity instanceof E) {
E e = (E) entity;
// 假設 code1 是第 3 個屬性(索引 2)
for (int i = 0; i < propertyNames.length; i++) {
if ("code1".equals(propertyNames[i])) {
state[i] = generateCode1(); // 你的生成邏輯
return true; // 表示 state 已修改
}
}
}
return false;
}
private String generateCode1() {
// 你的生成算法,如 UUID、雪花算法、業務編碼規則等
return "CODE-" + System.currentTimeMillis();
}
}
// 方式 1:SessionFactory 級別(全局生效)
Configuration cfg = new Configuration();
cfg.setInterceptor(new CodeGeneratorInterceptor());
SessionFactory sf = cfg.buildSessionFactory();
// 方式 2:單次 Session 級別(推薦,線程安全)
Session session = sessionFactory.openSession(new CodeGeneratorInterceptor());
Transaction tx = session.beginTransaction();
session.save(e);
tx.commit();
session.close();
state 數組包含所有將持久化的屬性值,可根據其他字段計算。| 方案 | 優點 | 缺點 |
|---|---|---|
| Entity @PrePersist | JPA 標準,簡單 | 無法訪問 Session/事務上下文,生成邏輯受限 |
| Service 手動設置 | 直觀可控 | 易忘、代碼分散、耦合業務邏輯 |
| Database Trigger | 數據庫級保證 | 跨庫遷移困難、調試難、業務邏輯下沉 |
| Interceptor (推薦) | 框架級、靈活、可訪問上下文 | 需理解 Hibernate 內部機制 |