Tracking last change to an object with @Version an

2019-07-11 15:16发布

问题:

Using JPA with EclipseLink, I would like to track the timestamp of the last update made to an entity instance. Assuming that this would be easy to combine with optimistic locking, I defined the entity as follows:

import javax.persistence.Version;
[...]

@Entity
public class Foo {
    @Id int id;
    @Version Timestamp lastChange;
    [...]
}

Updating a changed object is done with the following code:

EntityManager em = Persistence.createEntityManagerFactory("myConfiguration");
em.getTransaction().begin();
em.merge(foo);
em.getTransaction().commit();

I would expect that foo.lastChange would be set to the new timestamp each time an update to a changed instance is committed. However, while the field LASTCHANGE is updated in the database, it is not updated in the object itself. A second attempt to save the same object again thus fails with an OptimisticLockException. I know that EclipseLink allows to choose between storing the version-field in cache or directly in the object and I made sure that the configuration is set to IN_OBJECT.

The obvious question is: How to get the foo.lastChange field set to the updated timestamp value when saving to the database? Would

foo = em.find(Foo.class, foo.id);

be the only option? I suspect there must be a simpler way to this.

回答1:

merge does not modify its argument. It copies the state from its argument to the attached version of its argument, and returns the attached version. You should thus use

foo = em.merge(foo);
// ...
return foo;