-->
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.  [ 5 posts ] 
Author Message
 Post subject: Using hibernate in a Unit of Work scenario
PostPosted: Fri Oct 01, 2004 11:22 am 
Beginner
Beginner

Joined: Thu Feb 05, 2004 10:39 pm
Posts: 44
I am using hibernate 2.

Out application is structured around a UnitOfWork pattern. During a transaction all entities to be inserted/updated are put on one queue, and all entities to be deleted are put on another. These queues signify all work to be performed within one session with out application.

Once our application code has determined all business criteria for commit have been met, we loop over each queue and execute either a SaveOrUpdate command for all new/update entities or a delete operation for all entities on the delete queue.

The problem I am running into that we can have multiple instances representing the same i.e. account on the update queue.

So, for example, we have account to account fund transfers. During the same transaction, we might have 2 request to transfer funds from account 110 to 120 and then again from 110 to 130. First, we would do a find on account 110, update its values and put it on the update queue. For the second request (within the same transaction) again we would retrieve account 110, update it and put another instance of account 110 representing the second transfer on the update queue. At commit, the first reference updates fine, but the second instance is naturally out of synch with the database.

So, I am currently trying to remedy this through a refresh before saveOrupdate but don't know if this is the best approach. Any suggestions of how to remedy this in a better way?


Top
 Profile  
 
 Post subject: update...
PostPosted: Fri Oct 01, 2004 12:13 pm 
Beginner
Beginner

Joined: Thu Feb 05, 2004 10:39 pm
Posts: 44
Reading the documentation some more, I guess I need to point out that when the objects are first loaded, they are loaded in the same session as the save save/updated is performed in.

Having read the documentation some more, this would explain why an update happens to a previously loaded and changed object right before the next object is loaded from the db (I am assuming the find method flushes the session before a query).


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 04, 2004 5:06 pm 
Beginner
Beginner

Joined: Thu Feb 05, 2004 10:39 pm
Posts: 44
...ok, do I need to explain this better or does this problem not have a solution the way we currently do things?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 04, 2004 9:43 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
Yes you really need to explain this better. How about some code snippet or pseudo code for the processing you are describing.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 05, 2004 11:03 am 
Beginner
Beginner

Joined: Thu Feb 05, 2004 10:39 pm
Posts: 44
Steve, thanks for that input. Ok, here is maybe a bit better example, please bear with me:

Our application processes changes to user accounts. This is a webservices based system using SOAP. Each SOAP request entering the system can contain one or more account changes for one or more people. Sometimes, as in the case I am trying to troubleshoot, the request may contain two or more changes to the same account. Each SOAP request containing multiple account changes is considered one business transaction. Either all updates succeed or all get rolled back. This is what we consider a "Unit of Work".

The general application flow looks something like this (all this happens within the same hibernate session):

0. A SOAP request enters the system requesting changes to accounts 110, 120. There are 2 updates requested for account 110...so....
1. find account 110 for update
2. update account 110 with info
3. place reference to updated acct 110 in unit of work
4. find account 120 for update
5. update account 120 with new info
6. place reference to updated acct 120 in unit of work
7. again, find account 110 for update
8. update account 110 with info
9. place reference to updated acct 110 in unit of work
10. If no errors, execute commit

As our application processes each update contained in the incoming SOAP request, it makes the changes to the account entities and places a reference to each updated account into a UnitOfWork object. We have represented this Unit of Work as a simple class containing a list of accounts and the operation to be performed (delete/save). Our account objects use optimistic locking with timestamp versioning.

At commit, our application loops over each list and executes a session.delete() or session.saveOrupdate(). Then, once we know we don't have any exceptions, all change requests queued up are committed as a whole. If there are faults, all changes are rolled back.

Code:
session = getActiveSession();

            tx = session.beginTransaction( sessionContext );
         
            if( !ServiceRequestContext.getInstance().getSSPSOAPFault().hasFault() )
            {
            Iterator i = entityChanges.iterator();
            while( i.hasNext() )
            {
               EntityOperation entityOperation = (EntityOperation) i.next();               
               BaseEntity b = entityOperation.getEntity();
               Object op = entityOperation.getOperation();
                   
               // switch based on requested operation
               // == instead of equals() is OK because we're comparing static final String refs
               if(UnitOfWorkImpl.DELETE == op) {
                  
                  session.delete( b );
                  
               } else if (UnitOfWorkImpl.SAVE_OR_UPDATE == op) {
                  session.saveOrUpdate( b );
                  
               }
            }
            }

            tx.commit();
}


OK, and now the problem:

As you can see from the above list, acct 110 is fetched twice, updated twice with different info and referenced twice in our update list. When we loop over our accounts to commit the changes, the first flush to acct 110 executes fine but the second naturally causes a StaleObjectException since the second acct 110 reference's is now out of synch with the changes made to the first instance already flushed.

The reason we constructed our persistence logic like this is because we need tight control of what is considered a transaction and that we need to roll back a whole package worth of changes is something goes wrong anywhere. Naturally, in this case when we might have multiple changes to the same account we run into this problem.

I have experimented with FlushModes, second level cache and refreshing the accounts at different stages, but I still run into the same problem. Any ideas of how this either could be solved or redesigned?

Many thanks.


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