user1016403
user1016403

Reputation: 12621

issue with spring transaction management?

I am using spring and hibernate. i am using spring for transaction management. i have below class.

@Service
@Transactional(readOnly = true)
public class Sample implements SampleInterface{

@Override
public List<Some> getData(){

//gets data after that it updates something

setStatus(someId);

}

@Override
@Transactional
public void setStatus(Long someId){

//sets status

}

}

If i dont keep @Transactional for getData() then i get below exception.

Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode

if i keep @Transactional for getData() then it will save properly. what is an issue here? any how i have @Transactional for setStatus(). Still do i need to keep @Transactional for getData() as it is calling a public method which will set the status?

Thanks!

Upvotes: 1

Views: 170

Answers (2)

maneesh
maneesh

Reputation: 1112

When you call getData (without @Transactional on the method) Spring will start a read only transaction as that is the default for your class and when getData calls setStatus Spring will use the existing rad only transaction instead of creating a new one. That's the reason you are getting the exception.

The default transaction propagation is PROPAGATION REQUIRED. Read more on the topic at http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html#tx-propagation

Upvotes: 1

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 341003

The problem is a bit complex and is caused by calling setStatus() inside getData(). When you are calling getData() from outside, you are actually calling a Java proxy created for you by Spring framework. This proxy applies transaction behaviour (starts read-only transaction) and delegates to your actual service class. This works fine.

However, when you call setStatus(), you are bypassing the transactional proxy and calling your service directly. In other words the request to setStatus() is not intercepted, and @Transactional is ignored.

There is no easy way to deal with this problem and has the same issue. You just have to be extra careful when calling public methods inside the same class.

See also

Upvotes: 5

Related Questions