10 March 2009

Managing user Transaction in Hibernate

In the name of ALLAH,

Today we will talk about an important topic in doing Databases, User Transactions.

There are two types of transactions found in any Database application, Database Transactions and User(Application) Transactions. 

Database Transactions are transactions that executed as a serious of SQL statements sequentially, once completed, the transaction commits ( or rolled back ).

example of DB Transaction when a Bank Client what to transfer funds form his first account to his second account, that will be done in two stages, first decrement his first account with the amount he specified, second, add to his second account the amount he wishing transfer.

In such scenario, if one stage fails, the other should fail.

So if we implement these two stages as ordinary two SQL update statements, the DB couldn't ensure that the two will be committed or rolled back together, so the solution in Transactions.

In DB Transaction, the Transaction either committed or rolled back as a whole.

The Database Management System (DBMS) itself who ensure the Atomicity, Consistency , Isolation and Durability of these transactions (ACID).

So what ACID ??

ACID is a certain operations granted  to be executed by the database against DB Transaction.

Atomicity means : single unit of work ( either the transaction committed or rolled back at all )

Isolation means : no changes cannot made to the data used in the transaction, the transaction is isolated from other transaction and database changes (i.e. if another user want to change the data under transaction, he can't ).

Consistency means : the transaction shouldn't leave the data in non-consistent state.

Durability means : once the transaction committed, all changes during it, make persisted in the database.

But, what happened if the Transaction should be span multiple User Sessions ( not hibernate Session interface ) ?

In another meaning, suppose we have an Enterprise-based web application (Web Application), the user makes changes that are related and occurs in subsequent request-response cycle.

What if the user should change his bank account in 2 or more requests to the server ??

in this case, we cannot relay on Database Transactions, So here's the User (Application) Transaction arises .

User Transactions

We will take about user transaction in a context of a simple example, suppose we have an e-commerce web application, we have more that one administrator that can change the price of the products according to some criteria, what happens when two Administrators want to change the price of one product at the same time, the first administrator will change the price based on the original price say he changed the price of a laptop computer from 4000 L.E to 3800 L.E. And the other administrator change the price from also 4000L.E. ( he still didn't see the new changes of the database ) to 4200 L.E. ??

the second administrator thought that he changes the price from 4000 to 4200, but really he will change the price from 3800 ( that changed be the other administrator will he opened the changing page and not yet decided to change the price ) to 4200, the Owner never permit that a product be increased in price by 400 L.E. A once !!

So we have three choices as system implementers ..

1)      override the first administrator by the second administrator and set the price to 4200 ( violate the business rules )

2)      not to allow the second administrator to commit his changes saying that another administrator at the same time has already changed the price

3)      not to allow the second administrator to commit his changes and showing him the changes made by the other administrator.

Solution 2 & 3 are more reasonable, in first solution, hibernate have nothing to do, neither you.

In the second and third solution Hibernate come and get a solution to such a concurrency problems by using “Managed Versioning” .

In managed versioning, you will add a new column in the database called version ( for example ), and add a new property for the object to be persisted called version.

So far so good, the new thing is to add a tag called version immediately after the identifier property that reassemble :

< version name="version" column="version" >

that is all about, when hibernate is going to update the column it will issue a SQL statement looks like this :

UPDATE products p SET p.price = “4200” AND version = 1

WHERE p.id = 123  AND version = 0

if another transaction updated that column at the same time, the version id shouldn't contain the value 0, so the update statement will never executed and hibernate throws exception of type org.hibernate.StaleObjectStateException

No comments: