Question

This is my Repository layer:

class RepositoryImpl implements Repository{ 
    @Override
    public Serializable saveOrUpdate(Object obj) {      
        return getSession().save(obj);
    }

    @Override
    public Object get(Class refClass, Serializable key)
    {
            return getSession().get(refClass, key);
    }
}

This is my Service layer:

class ServiceImpl implements Service{

    @Autowired
    Repository repository;

    @Override
    @Transactional
    public Object findUserById(Serializable key) {
        // TODO Auto-generated method stub
        return repository.get(User.class,key);
    }

    @Override
    @Transactional
    public Serializable saveUser(Object o) {
        // TODO Auto-generated method stub
        return repository.saveOrUpdate(o);
    }   
}

Here I am accessing and updating objects asynchronously:

class SomeClass{
    @Autowired
    Service service;    
    public void asynchronousSaveOrUpdate(){
        User u = service.findUserbyId(1);
        service.saveUser(1);
    }
    public void asynchronousfindUsersById(){
        service.findUserbyId(1);
    }
}

I got this exception:

[1236]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.deadline.core.model.User#1236]
        at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:672)
        at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
        at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)

Note: I don't want Transactional for ServiceImpl.findUserById() method.

Doing @Transactional(readOnly =true) or @Transactional(propagation =Propagation.REQUIRES_NEW) will solve this problem?

By calling session.merge() this issue will be solved, however I cannot use it.

Was it helpful?

Solution

You'll have to provide a little more information about what is going on. Is this error occurring every time you save a user, or only when you call saveUser(user) at the same time from multiple threads? Or is it happening anytime you call findUserById() or saveUser()?

You might want to look into the Isolation parameter for the @Transactional annotation. The default is Isolation.DEFAULT (which is the "...default isolation level of the underlying datastore").

The way you are using this function should determine what value you want to supply for this argument. Will your saveUser(user) function almost always conflict with with another call to that function? Then you might want to use:

@Transactional(isolation = Isolation.READ_COMMITTED)

Edit: I will say it does sound like this is functioning properly, though. It makes sense that if your object is modified in another thread, and then you try to commit that same object from another thread at the same time, you'd get StaleObjectStateException

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