Frage

I am using Hibernate to implement the DAO layer (Sybase DB) in a web application running on Jboss5.

The problem I am facing is when the client/UI makes multiple simultaneous HTTP calls - which in-turn calls the DAO insert method - there is a race condition which causes both calls to run the DAO insert method at near same time. What I actually want is

  1. The 1st request calls the DAO method
  2. 1st request reads the current db value
  3. Check if new data is valid based on current db value
  4. If valid, insert the new value
  5. AND then the 2nd request to read the current db value
  6. Check if new data is valid
  7. If valid, insert the value...and so on if there are more calls

My DAO layer code looks like so:

@Override
@Transactional
public Set<PartyData> insertPartyData(final Set<PartyData> pData) throws DataServiceException
{
    sessionFactory.getCurrentSession().getTransaction().begin();
    //code to read the current db value
    //validation code to check if new value can be inserted based on what's currently in db
    sessionFactory.getCurrentSession().save(pData);
    sessionFactory.getCurrentSession().getTransaction().commit();
}

Question?

How can I make sure that the db locks the table for the duration of one transaction so that any other request waits until the previous transaction is complete?

War es hilfreich?

Lösung 3

* ANSWER *

Ok I have tried the below solution which seems to have worked so far.

What seems to happen is each request seems to create a new session and that session runs in its own transaction. So no two request seem to interfere with each other and each transaction runs in one go.

I am not an expert in hibernate so please correct me if this is not the right way to do it.

@Override
@Transactional
public Set<PartyData> insertPartyData(final Set<PartyData> pData) throws DataServiceException
{
    final Session session = sessionFactory.openSession();
    Transaction tx;
    try {
        tx = session.beginTransaction();
        \\read curren db value and do the validation with new data (throw exception if validation fails else continue)
        session.save(pData);
        }
        tx.commit();
    }
    catch (final Exception e) {
        throw new DataServiceException(e);
    }
    finally {
        session.close();
    }
    return pData;
}

Andere Tipps

While locking the table will work - the process of locking an entire table just doesn't seem right. There must be other ways to accomplish what you're trying to do, like unique constraints for example.

IMO this is best to be done in the container level rather than the application level (Don't know if it could even be done in the application level).

Based on this article, you can do what you like by configuring two attributes in the Connector.

Set maxThreads to 1 (maxThreads: The maximum number of request processing threads to be created by this connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200.)

This will make sure that you run exactly one request at each time.

Increase the acceptCount : (acceptCount: The maximum queue length for incoming connection requests, when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 10.)

This should be set relatively high so that you do not deny connections to your service, rather add then to queue untill another request finishes execution.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top