Question

I have the same module that connect with database running in two servers (back and front). Its connect with the same database.

I use JPA (Hibernate implementation) and Spring transaction management.

I have the following problem:

I have to update the fieldA from tableA with the MAX value + 1 of two different fields (fieldA from tableA, fieldB from tableB)

Case1:

Before update

tableA fA = 100

tableB fB = 102

After update

tableA fA = 103

tableB fB = 102


Case2:

Before update

tableA fA = 102

tableB fB = 100

After update

tableA fA = 103

tableB fB = 100

The method with this code is transactional and do things before (like create the entity) and after that. So before commit the transaction if the other application try to get the value, it will be outdated and it will save the same value in fieldA. Hibernate sessions are different because the distributed system.

I can't use sequences in database (legal issues because it is about invoicing) or distributed cache for Hibernate (system issues)

How i can do that??

thanks

Was it helpful?

Solution

You can use locking for that. The appropriate type of locking depends on your use case.

If the probability of a concurrent update is low, use optimistic locking. In case of an update collision, catch the Exception, refresh the entity, reapply your changes and retry the commit.

If you use optimistic locking, it is advised to add a @Version field to your entity. Optimistic locking without a version field is not guaranteed to be supported.

If the probability of a concurrent modification is high, use pessimistic locking. Thus you can serialize writes on the row. Note that this type of locking can create a bottleneck as transactions queue for updates and other transactions time out before acquiring the lock.

In order to minimize the lokc time, you can apply the lock on an individual query:

query.setLockMode(LockMode.WRITE)

EDIT: The locks can be probably used in a distributed environment safely.

Optimistic locking is implemented as a check on the @Version field in the DB at commit time (or equivalent) - with read-commited isolation (the default) there is no risk of missing a committed change to the entity.

Pessimistic locking is implemented on DB level, often using SELECT FOR UPDATE or similar. So you don't have to worry.

OTHER TIPS

You need pesimistic locking. With Hibernate you can do this on the JDBC or transaction level.

Read the chapter about locking in the hibernate manual.

I don't know if I understood correctly your question but maybe in your DAO you can prepare a method where you can do something this

DetachedCriteria dc = DetachedCriteria.forClass(ClassA);
dc.setProjection(Projections.max("id"));
logger.info(svc.getMax(dc));

Once you got the max value you can update the other table

Angelo

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top