-->
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: application transaction with timestamp
PostPosted: Thu Dec 16, 2004 1:08 pm 
Newbie

Joined: Thu Dec 16, 2004 12:56 pm
Posts: 9
Hi,
i need to manage this concurrency:
- user A edit a record
- user B edit the same record
- user A save
- when userB try to save, i expect an error (a StateObjectStateException), but all works fine and the last user win. What's worg? This is my mapping file :

<class name="hibernate.WeseUser" table="WESE_USER">
<id name="userId" type="java.lang.Long" column="USER_ID">
<generator class="sequence">
<param name="sequence">wese_user_seq</param>
</generator>
</id>

<timestamp name="userDataAggior" column="USER_DATA_AGGIOR" />

<property name="userNome" type="java.lang.String"column="USER_NOME" not-null="true" unique="true" length="30" />

...
</class>


Thk in advance,
Marco


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 16, 2004 1:26 pm 
Beginner
Beginner

Joined: Tue Oct 26, 2004 12:45 pm
Posts: 43
Location: Israel
Hi.

I have two suggestions:

1. look at the generated sql, and see if Hibernate really uses the timestamp in the update statement.

2. check your transaction isolation level (session.connection().getTransactionIsolation()).

Jus.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 17, 2004 4:40 am 
Newbie

Joined: Thu Dec 16, 2004 12:56 pm
Posts: 9
Hi. Issahar

1. yes, the timestamp is used by Hibernate int the update statement.
2. the transaction isolation level is TRANSACTION_READ_COMMITTED

Maybe the isolation lavel isn't correct?

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 19, 2004 4:56 am 
Beginner
Beginner

Joined: Tue Oct 26, 2004 12:45 pm
Posts: 43
Location: Israel
mrossix wrote:
Hi. Issahar

1. yes, the timestamp is used by Hibernate int the update statement.
2. the transaction isolation level is TRANSACTION_READ_COMMITTED

Maybe the isolation lavel isn't correct?

Thanks


As i understand - the transaction isolation allows just that, so i would debug and see why using the timestamp doesn't prevent the application from updating.
check the timestamp of the first retrieved row, and check the timestamp after the second transaction updated the row.

can't help more than that, sorry...

Jus.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 19, 2004 6:17 am 
Newbie

Joined: Thu Nov 18, 2004 12:32 pm
Posts: 8
Location: UK (Newcastle upon Tyne)
Well all I can recount is what I do and maybe that might help.

For example, I have an entity Organisation with org_id as primary key and name as (not null) attribute. I also have a version_number column for this entity. The bean looks like:

Code:
public class Organisation
{
   private long   orgId         = 0;
   private String   name         = null;
...
   /**
    *
    * @hibernate.id generator-class="assigned" column="org_id" type="long"
    *               unsaved-value="0"
    */
   public long getOrgId()
...
   /**
    * @hibernate.version column="version_number" type="integer"
    */
   public int getVersionNumber()




Now I have a session facade (since all of this runs inside JBoss and the facade is from my previous EJB project, being reused here).

Code:
public class OrganisationServiceBean implements javax.ejb.SessionBean
{
...
   /**
    *
    * @ejb.interface-method view-type="both"
    * @ejb.transaction type="Required"
    */
   public int updateOrganisation(Session session, long org_id, String name, int version_number)
   {
      Organisation organisation = null;
      try
      {
         organisation = (Organisation) session.get(Organisation.class, new Long(org_id));
1         if (organisation != null)
         {
2            if (version_number != organisation.getVersionNumber())
            {
               throw new StaleObjectStateException(Organisation.class, new Long(org_id));
            }
3            organisation.setName(name);
            session.saveOrUpdate(organisation);
            return 1;
         }
         return 0;
      }
      catch (Exception e)
      {
         throw new EJBException(e);
      }
      finally
      {
         organisation = null;
      }
   }


Test 1:
Now if I pause the code at line marked 1, use another unit test to update the same row, and then proceed with continue on the above paused thread:

- The version number check is not violated, but the "saveOrUpdate" throws a StaleObjectException.

Test 2:
However if I pause the code somewhere higher up (after the data has been got previously using another session) and then used another Unit test thread to updated the same row, its my

Code:
if (version_number != organisation.getVersionNumber())


bit of code that detects version violation.

Test 2 simulates a scenario where the data has been obtained in a previous session (followed by closing the transaction) when requested by a UI.

In this situation I think one has to manually check for version_number compatibility. If for some reason, the code passes the compatibility test at line 2 but, say, another thread updates the same row between lines 2 & 3, a StaleObjectException would still be thrown by Hibernate when saveOrUpdate is called. This is is not dissimilar to my EJB (JBoss 3.2.6) deployment anyway.

Of course in my case all of the above happens inside JBoss (4.0.1RC2).

Sorry about the length of this post but I hope it helps in some way (and I was rather hoping that someone, more in the know, would verify my take on Hibernate's behaviour).

Cheers
-raj

_________________
- cowboy maybe, but an injun at heart


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 19, 2004 6:50 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
What database and drivers are you using ? (oracle drivers has certain issues where they chop of milliseconds when comparing timestamps which make timestamps even more fragile than they are)

Are you sure you don't read the object saved by user A, in B's session before you update it ? (then you will not get an optimistic lock since you can read what A has committed with READ_COMMITTED) ...solution, change transaction level or simply just use the same exact object instance which B got in the first place (and learn the wonders of detached object as opposed to DTO's ;).

and a last comment....use version instead of timestamp as they are inherently more safer under highloads - just an advice.

_________________
Max
Don't forget to rate


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.