[hibernate-issues] [Hibernate-JIRA] Created: (HHH-3661) Optimistic's locking version number is incorrectly applied to the Entity in some cases

Juan F Cervera (JIRA) noreply at atlassian.com
Tue Dec 16 12:04:39 EST 2008


Optimistic's locking version number is incorrectly applied to the Entity in some cases
--------------------------------------------------------------------------------------

                 Key: HHH-3661
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3661
             Project: Hibernate Core
          Issue Type: Bug
          Components: core
    Affects Versions: 3.3.1
         Environment: Hibernate 3.3.1.GA and Informix 10
            Reporter: Juan F Cervera


Hi I have found an issue using optimistic locking and I think it's probably a bug.

The situation is the following:
a) I use optimistic locking
b) I have a legacy database where the optimistic locking field is controlled by triggers, so I use generated="always" in the mapping file for the version field (I don't think this is related to the problem, but wanted to clarify)
c) The Entity has a <bag> collection that can be empty (null)
d) At some point the collection is changed to something else than null, in my case this is happening within the same transaction, after creating the Entity, but this doesn't seem to be required for the problem to happen.

The above scenario produces a StaleStateException.

For what I see Hibernate first inserts the new record, then it does an update because we have added the collection but it uses the wrong version number, which produces the exception.

After some debugging I have traced down the problem, as follows:
a) As there has been a change to the Entity, Hibernate calculates a new version number (even when I have generated="always". This is not normally a problem though as it's not written to the DB.)

b) When an Entity has a collection that changes from null to something else, Hibernate substitutes the normal collection for the appropriate Hibernate collection type, in my case a PersistentBag. Unfortunately, the substitution process doesn't stop just at the collection, it applies to all the dirty fields, including the version number to the new calculated in a)!! This means that the version number is out of sync with the DB, which will produce problems down the line.
See the following for details:
+ Line 112 at org.hibernate.event.def.WrapVisitor.processArrayOrNewCollection forces the substitution by not returning new persistentCollection
+ This gets propagates several layers until it reaches the boolean "substitute" in line 148 at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity
+ This variable enforces the substitution in the line 156, where the version number gets updated to a new value which doesn't exist yet in the database, as the record has not been updated with it yet.

c) When the update happens, Hibernate queries the Entity for it's version number because it's using optimistic locking, and as this has been updated in b) with a new value that doesn't match the record in the database nothing gets updated
See following for details:
+ The "previous" version number is retrieved in the line 96 at org.hibernate.action.EntityUpdateAction.execute

d) Hibernate checks how many records have been updated, in this case 0 as the version number was wrong. Then it interprets this as a StaleStateException


Unfortunately I don't know enough about Hibernate to be able to propose a working solution. I think the fact that a full update of the Entity, including the new calculated version number, is forced in step b) is the issue and that the version number should have been left as it was.
How many other scenarios, apart from changing a null collection to one with data, would produce substitute to be "true" I don't know, but I expect all those cases to produce problems with optimistic locking in the same way.

I have work around for system that use the DB to control the version numbers instead of Hibernate (normally through triggers). In these systems it's possible to set optimistic-lock="false" in the collection, which would prevent the version number changing for updates on that field, so the update on b) would be fine. Unfortunately, if some other property changes along with the null collection, the version number will change because of those other properties. So in order to be sure I don't have issues I have had to set optimistic-lock="false" in all components/properties/collections.


One more thing, I think this issue is probably the cause to the problem reported in HHH-2796, as the symptoms look similar.

Let me know if you have any questions.

Thanks

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the hibernate-issues mailing list