我正在尝试将我的应用程序从spring 3.3.x升级到Spring 4.1。大多数升级都进展顺利,但我们发现有关交易传播的一些奇怪问题。我们有一个使用@Transactional(read-only = true)注释的服务层类方法,调用另一个用@Transactional注释的低层类方法(只读= false)。它们中的任何一个通过接口代理,日志显示TransactionInterceptor是调用。但是当我们在数据库上调用save时。
“连接是只读的。不允许导致数据修改的查询;”
弹簧的早期版本与弹簧4.0.9一样完美。但是一旦我切换到4.1,就会抛出这个错误。有任何想法吗 ?我的印象是,如果当前事务以只读方式启动并且我已经使用了一段时间,那么在调用期间任何时候都会将事务修改为读写。下面是我们正在做的事情的代码。我们使用Hibernate 4.1和JpaTransactionManager作为我们的事务管理器。
public class Service1Impl implements Service1{
public Service2 service2;
@Transactional(read-only=true)
public Job processJob( Data data){
.....
service2.saveJob(data);
}
}
public class Service2Impl implements Service2{
@Transactional(read-only=false)
public Job saveJob( Data data){
.....
}
}
非常感谢任何帮助或建议
由于
答案 0 :(得分:1)
属性read-only
不存在。它是readOnly
。
当事务管理器找到Transactional
注释时,所有代码都在一个全局事务中执行。由于您在Service1
中启动了只读事务,Transactional
注释将被Service2
忽略,并且不会提交任何更改。只有在您确定下划线交易中需要进行任何更改时,才使用readonly标志。如果您知道,注释方法将进行一些更改,或者如果它调用另一个正在修改数据的服务/方法,则永远不要使用readOnly=true
如果您想在readOnly=false
中使用Service2
新的transacton,可以使用此功能:
@Transactional(propagation=Propagation.REQUIRES_NEW)
public Job saveJob( Data data){...}
这将导致当您输入此方法时,事务管理器将始终启动新事务。但是这也可能会导致一些问题,因为如果在此方法中发生某些异常,则不会在启动此方法的事务中执行回滚(在这种情况下,事务在Service1
中启动)。
答案 1 :(得分:0)
发现这在4.1的春天得到了改善和解决。我在春季jira发布了这个问题,得到了回应
https://jira.spring.io/browse/SPR-12807
显然这是在春季3.x中打开的错误,但在4.1版本中解决了。最初的错误就在这里 https://jira.spring.io/browse/SPR-8959
所以它现在按照需要工作但是可以提供自定义的HibernateJpaDialect并将prepareConnection设置为false以默认为旧行为。
由于