spring事务管理的java问题?
我正在使用spring和hibernate。我正在使用spring进行事务管理。我有课下作业
@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
}
}
如果我没有为getData()保留@Transactional,那么我会得到下面的异常
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode
如果我为getData()保留@Transactional,那么它将正确保存。这里有什么问题?我有@Transactional for setStatus()的任何方法。当@Transactional for getData()调用将设置状态的公共方法时,我还需要保留它吗
谢谢
# 1 楼答案
这个问题有点复杂,是由在
getData()
内调用setStatus()
引起的。当您从外部调用getData()
时,实际上是在调用Spring框架为您创建的Java代理。此代理应用事务行为(启动只读事务)并委托给您的实际服务类。这个很好用但是,当您调用
setStatus()
时,您将绕过事务代理,直接调用您的服务。换句话说,对setStatus()
的请求不会被拦截,并且@Transactional
被忽略处理这个问题没有简单的方法,而且ejb也有同样的问题。在同一个类中调用公共方法时,只需格外小心
另见
# 2 楼答案
当您调用getData(方法上没有@Transactional)时,Spring将启动只读事务,因为这是您的类的默认事务;当getData调用setStatus时,Spring将使用现有的rad only事务,而不是创建新事务。这就是您获得异常的原因
默认事务传播是必需的。请在http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html#tx-propagation上阅读有关此主题的更多信息