Reputation: 12621
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
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
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 ejb has the same issue. You just have to be extra careful when calling public methods inside the same class.
Upvotes: 5