我正在使用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,那么它将正确保存。这是一个什么问题?我怎么用setStatus()的@Transactional。我还需要为getData()保留@Transactional,因为它调用了一个公共方法来设置状态吗?
谢谢!
答案 0 :(得分:5)
问题有点复杂,是由于调用 setStatus()
内的getData()
引起的。当您从外部调用getData()
时,实际上是在调用Spring框架为您创建的Java代理。此代理应用事务行为(启动只读事务)并委托给您的实际服务类。这很好。
但是,当您致电setStatus()
时,您绕过交易代理并直接致电您的服务。换句话说,setStatus()
的请求未被拦截,@Transactional
被忽略。
没有简单的方法可以解决这个问题,ejb也有同样的问题。在同一个类中调用公共方法时,您必须格外小心。
答案 1 :(得分:1)
当你调用getData(在方法上没有@Transactional)时,Spring将启动一个只读事务,因为这是你的类的默认值,当getData调用setStatus时,Spring将使用现有的rad only事务而不是创建一个新事务。这就是你获得例外的原因。
默认事务传播是PROPAGATION REQUIRED。在http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html#tx-propagation
了解有关该主题的更多信息