Spring @Transactional在每个服务方法结束时提交

时间:2015-02-27 05:53:49

标签: java spring jdbc vaadin spring-transactions

我在Vaadin,Spring项目中配置了一个通常的声明式事务管理。我在root-context.xml中添加了<tx:annotation-driven transaction-manager="transactionManager" />,在pom中添加了所有其他必需的maven依赖项。 我的服务方法使用默认传播@Transactional进行注释。

我想从UI方法中调用两个服务方法,期望这两个服务方法在单个事务中进行分区,因为默认传播是PROPAGATION_REQUIRED。但是这两种方法都是独立于db的。这意味着如果第二种方法失败,则第一种方法无论如何都要提交给数据库。我没有使用try{}catch{{块,因此任何RuntimeException都会被冒泡。

附有弹簧原木。删除一些行以减少#of行数

[qtp187048467-48] DEBUG o.s.j.d.DataSourceTransactionManager/getTransaction Creating new transaction with name [...UserServiceImpl.turnOnPwdResetFlag]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; [qtp187048467-48] DEBUG o.s.j.d.DataSourceTransactionManager/doBegin Switching JDBC Connection [com.jolbox.bonecp.ConnectionHandle@42398a05] to manual commit [qtp187048467-48] DEBUG o.s.j.d.DataSourceTransactionManager/handleExistingTransaction Participating in existing transaction [qtp187048467-48] DEBUG o.s.jdbc.core.JdbcTemplate/doInStatement SQL update affected 1 rows [qtp187048467-48] DEBUG o.s.j.d.DataSourceTransactionManager/processCommit Initiating transaction commit [qtp187048467-48] DEBUG o.s.j.d.DataSourceTransactionManager/doCommit Committing JDBC transaction on Connection [com.jolbox.bonecp.ConnectionHandle@42398a05] [qtp187048467-48] DEBUG o.s.jdbc.datasource.DataSourceUtils/doReleaseConnection Returning JDBC Connection to DataSource ` ` [qtp187048467-48] DEBUG o.s.j.d.DataSourceTransactionManager/getTransaction Creating new transaction with name [...UserServiceImpl.turnOffPwdResetFlag]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT;  [qtp187048467-48] DEBUG o.s.j.d.DataSourceTransactionManager/handleExistingTransaction Participating in existing transaction [qtp187048467-48] DEBUG o.s.jdbc.datasource.DataSourceUtils/doReleaseConnection Returning JDBC Connection to DataSource 

2 个答案:

答案 0 :(得分:6)

如果你想为两个方法调用都有一个事务,你必须确保调用这两个方法的方法也有事务注释,如下例所示:

@Transactional
public void callingMethod() {
    method1();
    method2();
}

@Transactional
public void method1() {
}

@Transactional
public void method2() {
}

答案 1 :(得分:1)

Spring transaction internals Open session in view filter的帮助下,我想出了一个解决方案。

根据第一个链接,在Spring MVC上下文中,事务在控制器上下文中开始,然后服务层中的@Transactional方法参与,创建或在已存在的事务之上创建另一个适当的事务。但是如果UI层不是Spring MVC,那么就不会发生这种情况。

Spring transaction flow

如此Spring transaction image所示,事务顾问是决定是提交事务还是标记回滚的人。因此,如果我们只是让服务方法代理创建事先不存在的事务,那么在该代理方法的最后,顾问程序决定提交事务。为了解决这个问题,我们必须在两个服务方法调用之前创建一个事务,因此这两个方法将加入事务而不是自己提交。

Hibernate上下文中,Spring MVC支持OpenSessionInView,它为每个请求创建一个事务。我所做的是创建一个类似的servlet过滤器,在请求开始时创建一个事务,并在过滤器链的末尾提交。这在Vaadin,Spring和JDBC环境中完美运行。如果您非常担心在每个HTTP请求上获取Spring事务并因此获取数据库连接,请尝试使用LazyConnectionDataSourceProxy

请在此处查看解决方案:I want to... Use JDBC, Spring transactions and @Transactional