I'm using PreInsert and PreUpdate EventListeners in Hibernate to set the value of "created" and "updated" timestamps prior to writing my entity to the database. The problem is the next time Hibernate reads then flushes the entity Hibernate sees the changed timestamps and thinks the object needs to be updated even if nothing else changed. So the listeners are fired again, an update occurs, and the same over and over.
Ideally I'd like to be able to assign these timestamps without Hibernate thinking the object is dirty the next time it is flushed. What is the开发者_如何学C best solution for handling this? I assume I could override the dirty check, but I wanted to see what others do.
Here's some example code for reference (This is just sample code so no need to nitpick):
@Entity
class MyEntity {
@Id
Long id = Long.valueOf(1);
@Temporal(TemporalType.TIMESTAMP)
private Date created;
@Temporal(TemporalType.TIMESTAMP)
private Date updated;
@Override
public void setCreated(Date created) {
this.created = created;
}
@Override
public void setUpdated(Date updated) {
this.updated = updated;
}
}
public class PreInsertAndUpdateEventListener implements PreInsertEventListener, PreUpdateEventListener {
@Override
public boolean onPreUpdate(PreUpdateEvent event) {
MyEntity.class.cast(event.getEntity()).setUpdated(new Date());
return false;
}
@Override
public boolean onPreInsert(PreInsertEvent event) {
MyEntity.class.cast(event.getEntity()).setCreated(new Date());
return false;
}
}
public void updatedTest() {
Session session = sessionFactory.openSession();
Transaction t = session.beginTransaction();
MyEntity p = new MyEntity();
Serializable id = session.save(p);
session.flush();
for (int i = 0; i < 5; i++) {
p = (MyEntity) session.get(MyEntity.class, id);
session.update(p);
session.flush(); // Update always fires here
}
t.commit();
session.close();
}
The solution I decided to take was to update Hibernate's state to match that of the entity each time I modify the entity via an event listener. The implementation looks something like this:
StandardProperty[] properties = event.getPersister().getEntityMetamodel().getProperties();
Object[] state = event.getState();
for (int i = 0; i < properties.length; i++) {
if (properties[i].getName().equals("updated")) {
state[i] = timestamp;
break;
}
}
精彩评论