Eclipselink JPA merge problem [message #696768] |
Thu, 14 July 2011 19:36 |
Jeroen Peelaerts Messages: 8 Registered: July 2011 |
Junior Member |
|
|
Dear,
I have been using Eclipselink 2.3 for a while in my standalone J2SE swing application, communicating with a remote MySQL database. Lately I have been experiencing some problems with merging entities. It seems that when calling merge, Eclipselink sometimes does not commit changes made to recently detached persisted entities. Here a log dump showing the exact problem
12:01:08,078 [INFO] [JpaDao#pool-1-thread-2] - Merging Gert Eyskens
12:01:08,078 [DEBUG] [RunwalkVideoApp$RunwalkLogger#pool-1-thread-2] - SELECT 1
12:01:08,078 [DEBUG] [RunwalkVideoApp$RunwalkLogger#pool-1-thread-2] - communication_failure_attempting_begintransaction_retry
12:01:08,078 [DEBUG] [RunwalkVideoApp$RunwalkLogger#pool-1-thread-2] - disconnect
12:01:08,078 [DEBUG] [RunwalkVideoApp$RunwalkLogger#pool-1-thread-2] - connecting
12:01:08,109 [INFO] [StatusPanel#AWT-EventQueue-0] - Wijzigingen bewaren..
12:01:08,234 [DEBUG] [RunwalkVideoApp$RunwalkLogger#pool-1-thread-2] - connected_user_database_driver
12:01:08,250 [DEBUG] [RunwalkVideoApp$RunwalkLogger#pool-1-thread-2] - UPDATE phppos_people SET VERSION = ? WHERE ((person_id = ?) AND (VERSION = ?))
bind => [2, 5155, 1]
12:01:08,281 [DEBUG] [RunwalkVideoApp$RunwalkLogger#pool-1-thread-2] - UPDATE analysis SET COMMENTS = ? WHERE (id = ?)
bind => [2160 m 10 narrow , 8011]
Entity and DAO source code can be found in attachment.
When creating a person entity in my swing application, it is persisted to the database first with an empty last name and firstname. This way it can have an id generated for the hashcode and equals to be consistent. After this, it is detached (tx after persist is closed) and added to a List which is shown in the GUI using the beans binding framework.
At that time, the user can edit the entity, and when he is done, save and merge the changes using the entityManager.merge opertation.
the entityManager.merge operation starts at the first line. There a person.toString() is dumped to the log, where one can clearly see that the name and the first name of the person entity are set by the user. 80% of the time the changed first name and last name are commited to the db.
By analyzing the eclipselink logging for a while now, I found that Eclipselink sometimes seems to refresh the entity from the database before performing an UPDATE, and sometimes not.
Can anybody here tell me when Eclipselink decides to check the values of an entity with the database when using the AUTO (=DEFERRED) change tracking setting ? I feel that this can be a possible reason to this issue. that Eclipselink thinks the entity in its cache is the latest version and takes the state of the entity as it was persisted at first to make the merge (so with empty last name and first name). Does anybody know a programmatical way to invalidate the cache here and force eclipselink to make a lookup before merging (so bypassing the change tracking algorithm)?
At this moment, I do not use any weaving for compatbility reasons (beans bindings seems to have trouble with it), so changeTracking should prolly stick with DEFERRED. I have heavily optimized the logic behind the merging, and only entities that are really dirty (edited by the user) are merged to the db. So invalidating the cache should not have too much of a performance impact here.
Thanks in advance
-
Attachment: JpaDao.java
(Size: 5.41KB, Downloaded 584 times) -
Attachment: Person.java
(Size: 4.32KB, Downloaded 445 times)
|
|
|
|
|
Re: Eclipselink JPA merge problem [message #701050 is a reply to message #698133] |
Sun, 24 July 2011 14:07 |
Jeroen Peelaerts Messages: 8 Registered: July 2011 |
Junior Member |
|
|
Ok after adding the logging I have another clue on what is going on here. It seems that eclipselink is maintaining an up to date version in its persistence context after persisting the person entity the first time using em.persist() . I added a em.find() before the em.merge() and it seems that when the entity retrieved from the find() has a different name and firstname, eclipselink will go back to the db to query for this entity and do the updates correctly. In this case, it seems that the entity is not directly available from the persistence context.
When the find() returns an entity that has the same name, eclipselink will not go back to the db, as shown in the logging in my first post, and wil fail to save the updated entity. In this case, the entity seems to be available from the persistence context, despite being detached.
I'm wondering why sometimes these entities are up to date in the persistence context while the transaction in which they were persisted at first was committed and the related entitymanager closed. When I do a merge, they should not be available from the persistence context according to the jpa spec, or do I need to do a clear() after persisting every entity anyway?
For some reason eclipselink seems to be keeping track of the entity in its persistence context after it is persisted using persist(), even when the tx was committed and the entitymanager closed. Does anybody have a reasonable explanation for this?
Thanks.
|
|
|
(no subject) [message #701052 is a reply to message #698133] |
Sun, 24 July 2011 14:07 |
Jeroen Peelaerts Messages: 8 Registered: July 2011 |
Junior Member |
|
|
Ok after adding the logging I have another clue on what is going on here. It seems that eclipselink is maintaining an up to date version in its persistence context after persisting the person entity the first time using em.persist() . I added a em.find() before the em.merge() and it seems that when the entity retrieved from the find() has a different name and firstname, eclipselink will go back to the db to query for this entity and do the updates correctly. In this case, it seems that the entity is not directly available from the persistence context.
When the find() returns an entity that has the same name, eclipselink will not go back to the db, as shown in the logging in my first post, and wil fail to save the updated entity. In this case, the entity seems to be available from the persistence context, despite being detached.
I'm wondering why sometimes these entities are up to date in the persistence context while the transaction in which they were persisted at first was committed and the related entitymanager closed. When I do a merge, they should not be available from the persistence context according to the jpa spec, or do I need to do a clear() after persisting every entity anyway?
For some reason eclipselink seems to be keeping track of the entity in its persistence context after it is persisted using persist(), even when the tx was committed and the entitymanager closed. Does anybody have a reasonable explanation for this?
Thanks.
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03036 seconds