Hibernate (JPA): how to handle StaleObjectStateException when several object has been modified and commited

Marcus picture Marcus · Jan 29, 2011 · Viewed 15.4k times · Source

Consider the scenario: A Db transaction envolving more than one row from different tables with versioning.

For example: A shopLists and products. Where a shopList may contain products (with their amount in the shoplist) and products have their current stock.

When I insert ou edit a shopList, I want the stock of those products in the shopList to be updated to keep the stock consistant.

To do that, I open a transaction, insert/update the shopList, update the stocks for each product (apply delta) and then commit the transaction. No big deal up to now.

However, other user may have updated one or more products in common. Or even updated the shopList itself. In both cases, I would get a StaleObjectStateException when commiting the transaction.

Question is: Is there a way to determine which table caused the StaleObjectStateException?

In case the product caused the exception, I could refresh all envolved products from the DB and then reapply the stock deltas. And that's fine. In case the shopList caused the exception, it would be better to simply report the issue to the user so he could start over again.

Thanks very much for your help.

Answer

Marcus picture Marcus · Jan 30, 2011

I found out how.

First things first: the JPA (or the hibernate itself) wraps the org.hibernate.StaleObjectStateException exception as javax.persistence.OptimisticLockException. So, if you want to catch the right exception, go for OptimisticLockException.

Second: The hibernate will only throw the OptimisticLockException when you call EntityManager's method Flush before commit. If you call Commit directly you will get another exception instead (I've forgot which). Considering almost everyone catches those exceptions issued by the commit method and go for a transaction rollback, you'll get a Rollback's related exception (can't remember which once again).

Third and finaly answering my original question: You just have to call the getEntity method from the OptimisticLockException instance to get the origin of the Versioning error. That's going to provide you anything you need related to that.

Thanks for all of those who passed by here. Any questions regarding that, just ask and I'll be glad to help.