2012-08-14 155 views
1

我使用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 

} 

} 

如果我不保留@Transactional getData()然后我得到异常下面。

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

如果我保留@Transactional getData(),那么它将正确保存。这里有什么问题?任何我有@Transactional为setStatus()。我还需要为getData()保留@Transactional,因为它正在调用将设置状态的公共方法?

谢谢!

回答

5

这个问题有点复杂,是由 内部getData()造成的。当你从外部调用getData()时,实际上你正在调用Spring框架为你创建的Java代理。此代理应用事务行为(启动只读事务)并委托给您的实际服务类。这工作正常。

但是,当您拨打setStatus()时,您将绕过事务代理并直接调用您的服务。换句话说,对setStatus()的请求不被拦截,并且@Transactional被忽略

有没有简单的方法来处理这个问题,也有同样的问题。调用同一个类中的公共方法时,您必须格外小心。

+0

感谢您的回复。如果我保留@Transactional getData(),那么我的问题就解决了。这是不错的做法吗? – user1016403 2012-08-14 11:17:59

+0

@ user1016403:这不是最好的方法,但我没有找到更好的方法。你*可以*提取'setStatus()',但它不会解决你的特定问题。 – 2012-08-14 11:32:25

+0

感谢您的回复! – user1016403 2012-08-14 11:46:40

1

当你(在方法不@Transactional)调用的getData春天将开始一个只读的事务作为是你的类的默认值,当getData调用时,setStatus Spring将使用现有的只有rad的事务,而不是创建一个新的。这就是你获得例外的原因。

缺省事务传播是PROPAGATION REQUIRED。阅读更多关于主题http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html#tx-propagation

+0

恕我直言,在这种特殊情况下'@Transactional'注释被完全忽略。即使使用REQUIRES_NEW传播也会产生相同的错误。 – 2012-08-14 11:17:51