问题
I am working with OpenJPA 2.2.1 and would like to do the following:
1) Load an entity 2) Change the entity 3) Check the changes done before saving the entity
What I've done:
1) Load the entity via
EntityManager.find(MyObject.class, id);
2) Ok, pretty clear, I think, something like
MyObject obj = EntityManager.find(MyObject.class, id);
obj.setName("New name");
3) Tried to evict the object from the PersistenceContext and loading it again from the database via:
EntityManager.evict(MyObject.class, id);
EntityManager.find(MyObject.class, id);
The entity returned by the find() call in 3) is always equal (equal ID) to the entity found in 1)
I thought I could remove the entity from the PersistenceContext / cache by evict.
How can I achieve to have two different entities: a) the changed entity and b) the original entity from the database loaded in step 3)
And: If i refresh() the entity I expect the find method to return the refreshed one. Is that correct?
I tried the @PreUpdate listeners too with the same result so I think there must be something I have not understood regarding JPA PersistenceContext or Java references...
I hope I provided enough information! Thanks in advance!
回答1:
For a good overview of the JPA lifecycle I found this site (particularly the state diagram) to be helpful: http://www.objectdb.com/java/jpa/persistence/managed
The main take-away is that objects don't "disappear" when you remove them from the persistence context. Your obj will still point to a fully initialized MyObject with name set to "New name". The only difference is that committing the transaction/flushing the persistence context will no longer update the corresponding database entry.
You have several options when you want to look at the changes to obj before committing to the database. If quick and dirty suffices, I'd suggest
MyObject original = obj.clone();
and compare obj and original with whatever tool (or just plain printing both to your log) you like.
Regarding refresh(), have a look at what this page says:
The content of the managed object in memory is discarded (including changes, if any) and replaced by data that is retrieved from the database. This might be useful to ensure that the application deals with the most up to date version of an entity object, just in case it might have been changed by another EntityManager since it was retrieved.
回答2:
If you use Spring @Transactional like me. You can do the following:
@Transactional
MyEntityObject update(MyEntityObject myEntityObject){
boolean isNameChanged;
em.detach(myEntityObject);
MyEntityObject inDBObject = em.load(myEntityObject.getId());
isNameChanged = (myEntityObject.getName() != inDBObject.getName());
}
回答3:
How about:
1/ Read (or find) the object into memory [which is what you have done]
2/ Remove the object from the store; something along the lines of:
em.getTransaction().begin();
em.remove(obj);
em.getTransaction().commit();
3/ Do whatever updates on the object in memory;
obj.setName("My New Name");
4/ Finally persist the updated object:
em.getTransaction().begin();
em.persist(obj);
em.getTransaction().commit();
The above snippets are based on the javax.persistence.*; package and em is an instance defined like so:
EntityManagerFactory emFactory = Persistence.createEntityManagerFactory(PERSISTENT_UNIT);
EntityManager em = emFactory.createEntityManager();
All the best!
来源:https://stackoverflow.com/questions/17994433/howto-compare-two-entities-in-jpa-onpreupdate