-->
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.  [ 3 posts ] 
Author Message
 Post subject: Mostly Stateless Optimistic Locking
PostPosted: Thu Oct 18, 2007 2:43 pm 
Newbie

Joined: Wed Oct 17, 2007 6:41 pm
Posts: 4
I would like to use the "Many sessions with automatic versioning" approach to optimistic concurrency control e.g.:
Code:
// foo is an instance loaded by a previous Session
foo.Property = "bar";
session = factory.OpenSession();
transaction = session.BeginTransaction();
session.SaveOrUpdate(foo);
session.Flush();
transaction.Commit();
session.Close();


This implies that the object to be updated must be held in user state (i.e serialized to ViewState or saved in Session). However, in a scalable stateless web application, objects will not be preserved between requests. In this case each interaction with the database occurs in a new ISession that reloads all persistent instances from the database before manipulating them.

Unfortunately, it seems NHibernate does not support automatic versioning with completely reloading during each session. Ideally I would just store the object's version in viewstate during the first read. When the user decides to update, the persistent instance is reloaded from the database, and modified including setting the version to what it was originally. (Essentially recreating the state of the object as it was during the first read - not as it might currently be in the database). Then when it is submitted back for an update the version value stored in the instance is automatically made part of the where clause as usual.

Code:
//First Request (display the object in editing form)
session = factory.OpenSession();
foo = session.Load<Foo>(id);
TextBox1.Text =foo.Property;
ViewState["FooVersion"] = foo.Version;
session.Close();

//Meanwhile, another user updated this foo, and changes the version

//Next Request (PostBack)
session = factory.OpenSession();
foo = session.Load<Foo>(id);
foo.Property = TextBox1.Text;
foo.Version = (DateTime)ViewState["Version"];
transaction = session.BeginTransaction();
session.Update(foo);
session.Flush();
transaction.Commit();
session.Close();

//Now if the update query has the original version in the where clause, it will correctly fail since another user has modified foo since the original read.





Please let me know if this makes any sense in NHibernate. (This is how I have successfully implemented stateless optimistic locking using another O/R mapper, so I assume it should be possible wiht NH.)

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 18, 2007 6:44 pm 
Newbie

Joined: Wed Oct 17, 2007 6:41 pm
Posts: 4
We have found a solution. The trick is to remove the object from the session at some point before updating. This forces the update query to use the value of the version field that you have yourself set (not the value returned by the most recent Load). So...


Code:
//First Request (display the object in editing form)
session = factory.OpenSession();
foo = session.Load<Foo>(id);
TextBox1.Text =foo.Property;
ViewState["FooVersion"] = foo.Version;
session.Close();

//Meanwhile, another user updates this foo, and changes the version

//Next Request (PostBack)
session = factory.OpenSession();
foo = session.Load<Foo>(id);
foo.Property = TextBox1.Text;
foo.Version = (DateTime)ViewState["Version"];
[b]session.Evict(foo);[/b]
transaction = session.BeginTransaction();
session.Update(foo);
session.Flush();
transaction.Commit();   //throws exception here (a good thing!)
session.Close();


Voila! the version that was saved in ViewState is used in the WHERE clause (not the current version value in the db) thus correctly enforcing the optimistic concurrency check. Now can be completely stateless between calls (except for the version value), and the rest of the versioning is handled by NHibernate behind the scenes.

Hope that helps someone...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 19, 2007 9:55 am 
Newbie

Joined: Thu Oct 18, 2007 1:10 pm
Posts: 9
That is cool. Looks like Evict does what it is supposed to do.

I am wondering how manageable it is if we have 100s of entities and we need to maintain their versions in the view state and what would happen if 1000 of users are trying to go through the update. Is it a scalable solution?

If the database has a Version column, the version checking for controlling optimistic concurrency can be automatted by specifying the generated property as 'always' as I mentioned in my another post at
http://forum.hibernate.org/viewtopic.ph ... 27#2367327

With respect to the followinng code, could you please let me know if the update query generated by NHibernate contains SET statements for only the dirty fields i.e Property. Is it updating the Version field in the database?

foo.Property = TextBox1.Text;
foo.Version = (DateTime)ViewState["Version"];
session.Evict(foo);
transaction = session.BeginTransaction();
session.Update(foo);


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 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.