我正在使用没有注释的直接Hibernate 3.0。
在保存或更新域对象时,我希望Hibernate自动生成CREATE_DT和UPDATE_DT字段,而不是使用数据库触发器。
实现此目标的最佳做法是什么?
背景是我有一个从客户端传递的对象图,它包含多个对象。其中一些最终将被插入,其他更新。我可以在客户端设置日期,但这不是一个好主意。在服务器上设置日期意味着我必须在图表中搜索并检测更改。
在我看来,Hibernate会有一个实现这一目标的工具,但它并没有向我跳出来。
答案 0 :(得分:1)
不使用触发器的Hibernate方法是使用Hibernate的event architecture并注册PreInsertEvent
,PreUpdateEvent
或SaveOrUpdateEvent
的监听器(看一下用于完整列表的org.hibernate.event
包来设置和更新创建/更新日期。
另一种选择是使用interceptor,Session
- 范围或SessionFactory
- 作用域,设置创建和更新日期<{1}}中的和onSave(...)
中的更新日期。
如果有其他选项,请查看此previous answer。
答案 1 :(得分:0)
根据我实现这一目标的最简单方法是将这些字段作为属性放入对象类中,并通过构造函数私有地设置它们。如果要更改属性值,请将DateUpdated(例如)设置为DateTime.Now(或Java中的任何内容)。
一旦您的实体被持久化,它将自动保存这些日期并将它们保存到您的基础数据库。
它不是直接与Hibernate一起使用,但我认为这个解决方案比使用拦截器更容易实现。
希望这有帮助!
答案 2 :(得分:0)
我正在检查Pascal的答案作为正确的答案,因为他直接指出了提供详细信息和示例代码的文档中的要点。但对于读者来说,我在这里添加更多细节。
我尝试了hibernate事件和拦截器,发现拦截器在我的情况下工作得更好。它实施起来相对容易。
感谢您的帮助!
下面是拦截器的代码:
public class AuditInterceptor extends EmptyInterceptor {
private Log log = LogFactory.getLog(this.getClass());
private int updates;
private int creates;
@Override
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
if (entity instanceof AuditableVO) {
creates++;
// Find the create date and change it
for (int i=0; i < propertyNames.length; i++) {
if (propertyNames[i].equals("createDate")) {
state[i] = new Date();
return true;
}
}
}
return false;
}
@Override
public boolean onFlushDirty(Object entity, Serializable id,
Object[] currentState, Object[] previousState,
String[] propertyNames, Type[] types) {
if (entity instanceof AuditableVO) {
updates++;
// Find the update date and change it
for (int i=0; i < propertyNames.length; i++) {
if (propertyNames[i].equals("updateDate")) {
currentState[i] = new Date();
return true;
}
}
}
return false;
}
@Override
public void afterTransactionCompletion(Transaction tx) {
if (tx.wasCommitted()) {
log.info("Creations: " + creates + ", Updates: " + updates);
}
creates = 0;
updates = 0;
super.afterTransactionCompletion(tx);
}
}