These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Collections, Versions, and concurrency
PostPosted: Sat Jun 03, 2006 2:55 am 
Newbie

Joined: Fri Apr 21, 2006 5:33 pm
Posts: 12
Hi everyone,

I have a question around the semantics of collections and their parents. On page 171 of HiA, it says:

"Hibernate will increment the version number whenever an object is dirty. This includes all dirty properties, whether they're single valued or collections."

I think this has a negative impact on the way concurrency will work for certain situations. Consider the following code:

Code:
Public Class Patient
    Public Property ID() As Integer
    Public Property Version() As Integer

    Public Property Name() As String
    Public Property DateOfBirth() As String

    Public Property Addresses() As IList
    Public Property Consultations() As IList
End Class


Now consider 2 users working simultaneously:
1) User A opens the patient record
2) User B opens the same patient record
3) User A adds a new 'Address' object to the 'Addresses' collection
4) User B adds a new 'Consultantion' object to the 'Consultations' collection
5) User B saves the change
6) User A tries to save the change, but receives a 'StaleObjectException'

Whilst I agree that 'Patient.Version' should be incrememted, it shouldn't prevent User A from saving their changes (the business sees these as unrelated operations).

Does anyone agree with this? Is there an alternative solution to the problem?

Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 03, 2006 4:17 am 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
your answer lies in the next paragraph. basically your application needs to handle the exception and allow the user to merge changes. or, your DAO can call Lock() on the object setting the appropriate lock mode (lockMode.Read or LockMode.Upgrade) which would force NH to re-load the object from the cache before calling Save(). even with setting the lock mode, you're still going to have to offer some sort of visual interface that would allow the user to manually merge the changes. much like a source code control system...

-devon


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 03, 2006 9:13 am 
Newbie

Joined: Fri Apr 21, 2006 5:33 pm
Posts: 12
Thanks Devonl.

I appreciate the comments about merging records (I'm planning to do this also), but the point that I'm trying to make is that no values on the Patient object have changed - it is dirty because objects were added to the collection properties. Take a moment to consider what the 'Merge' UI will show. None of the values will have changed, so each collection's count will need to be compared. This could be a performance problem as each property would need to be loaded in order to do the comparison.

I'm wondering whether NH should relax the rules on versioning, and let the developer state when the version gets updated. In the example I gave in the original post, the two collections are semantically unrelated, so maybe the mapping would be something like this:

<property name="Addresses" ... promote-version="false">
<property name="Collections" ... promote-version="false">

This is some 'off the cuff' thinking, so may be completely flawed!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 03, 2006 11:09 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
Vij wrote:
I'm wondering whether NH should relax the rules on versioning, and let the developer state when the version gets updated. In the example I gave in the original post, the two collections are semantically unrelated, so maybe the mapping would be something like this:


I think that You can achive this with current capabilities. I haven't tested any of that, so it might not work actually... But:

1. Map collaction with inverse="true".
2. When adding element to collection, don't actually update the collection itself. Just do
Address addr = new Address();
addr.Patient = patient;
Session.Save(addr)

After that You must refresh the patient's address collection. The patients version property would not be incremented AFAIK. But if You want version to be incremented, Youll propably have to live with StaleObjectException :-P


Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject: increment version column of collections
PostPosted: Thu Dec 14, 2006 11:05 am 
Newbie

Joined: Fri Dec 01, 2006 11:36 am
Posts: 6
I use Version tag to manage concurrency. When i load a specific person like this (person holds 2 collections, history, address):

ISession session1 = _sessionFac.OpenSession();
ITransaction trans1 = session1.BeginTransaction();
person = session.CreateCriteria(typeof(Person))
.Add(Expression.Eq("Name", xyz))
.SetMaxResults(1)
.List();
trans1.Commit();
session1.Close();


Then i DON'T make any changes and save it:

ISession session2 = _sessionFac.OpenSession();
ITransaction trans2 = session2.BeginTransaction();
session2.SaveorUpdate(person)
session2.Flush();
trans2.Commit();
session2.Close();

Then the column version in all 3 tables are incremented +1. Shouldn't they be incremented, only if something has changed?


    2) And if i change/add a new history between the 2 sessions. version column of address is incremented, too. But why? Shouldn't only the version column inperson and address be incremented?
    3) If 2 users load the same person, user A changes an address, user B changes a history, user A saves person , user B gets of course a StaleObjectException while saveorupdate(person). I do understand, why StaleObjectException is coming in this case (person version is higher). But i think, when user A saves person, only person and address version column has to be incremented? And user B at least can save history?



Am i misunderstanding something or is something wrong in the mappings? In the DB, type of version is int, not null.

Code:
<class name="Person" table="Person" lazy="false">

<id name="PNr" column="PNr" type="Int32" unsaved-value="null">
<generator class="native"/>
</id>
<version name="Version" column="version" type="Int32" unsaved-value="0"  />
   
<bag name="AddressList" inverse="true" lazy="false" cascade="save-update" >
<key column="PNr" />
<one-to-many class="Address" />
</bag>

<bag name="HistoryList" inverse="true" lazy="false" cascade="save-update" >
<key column="PNr" />
<one-to-many class="History" />
</bag>





<class name="Address" table="Address"  dynamic-update="true" dynamic-insert="true" >
<version name="Version" column="version" type="Int32" unsaved-value="0" />
<many-to-one name="PNr" column="PNr" class="Person" update="false"/>




<class name="History" table="History"  dynamic-update="true" dynamic-insert="true" >
<version name="Version" column="version" type="Int32" unsaved-value="0" />
<many-to-one name="PNr" column="PNr" class="Person" update="false"/>



Top
 Profile  
 
 Post subject: Re: increment version column of collections
PostPosted: Thu Dec 14, 2006 3:11 pm 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
riz wrote:
Then the column version in all 3 tables are incremented +1. Shouldn't they be incremented, only if something has changed?


AFAIK, NHIbernate is not able to deterimine whether the objest is changed or not if the object is obtained from one session and the updated trought different session. So, it just assumes that data is changed and performs the update.

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.