我正在尝试在我的新Spring Boot + MyBatis应用程序中使用Spring Transaction Management。
到目前为止,我已经设法让所有事情都处理最少的问题 - 它只是让@Transactional
注释正常运行。目前,无论方法是否注释,所有语句都会立即提交。
Spring Boot为你做了很多样板配置,很难找到缺失的链接。
我的build.gradle
包含以下依赖项:
compile("org.springframework.boot:spring-boot-starter-amqp")
compile("org.mybatis.spring.boot:mybatis-spring-boot-starter:1.0.0")
compile("mysql:mysql-connector-java:5.1.38")
我的application.properties
包含以下数据源配置:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/my_db
spring.datasource.username=my_user
spring.datasource.password=my_pass
bean中未按预期运行的方法的一个简单示例如下:
@Transactional
public void performTransactionTest() throws Exception {
Person person = new Person();
person.setPersonId(123);
personMapper.insert(person);
throw new Exception("This should force a rollback!");
}
抛出异常但已插入记录。
目前Spring Boot和MyBatis的事务配置基本上没有相关的文档,但据我所知,它应该主要是自己连接起来,就像在Spring + MyBatis应用程序中手动完成一样,它不在 - 我们可以进一步配置它。话虽如此,我已经尝试了applicationContext.xml
中的以下配置而没有运气:
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
我可以确认,即使没有上述任何配置,DataSourceTransactionManager也配置了MyBatis mappers的SqlSession使用的相同DataSource。
任何有助于我朝着正确方向前进的帮助或想法都将不胜感激。如果您需要任何进一步的信息,我很乐意提供!
提前致谢!
Xandel
答案 0 :(得分:3)
所以我通过使用@Transactional
而不是方法定义来注释类定义来实现它。
我不确定这是否是常见做法。 Spring Boot事务管理文档不像here那样做,但Mybatis Spring示例确实在他们的文档here中这样做...
如果有人有进一步的信息可以解释这一点,我会很乐意将答案标记为正确答案。
现在,我的问题已经解决了。
修改强>
回到这个问题的一个月之后,我终于找到了它的底部。这里有两个主要问题。
正如Kazuki正确提到的那样,您需要使用@Transactional(rollbackFor = Exception.class)
注释明确声明需要对已检查的异常进行回滚。
&#34;只有通过Spring代理调用正确注释的方法时,才会创建事务边界。这意味着您需要直接通过@Autowired bean调用带注释的方法,否则事务将永远不会启动。&#34; (参考下面的这个来源)
在我的示例代码中,我从同一个类调用了this.performTransactionTest()
。这样,交易将被忽略。如果我通过有线引用来调用它,例如myAutoWiredBean.performTransactionTest()
,那么一切都按预期工作。这也解释了为什么只有类级注释才起作用,但那是因为任何被调用的方法都会被有线bean引用。
有两篇文章是我在帮助我理解Spring交易管理的细节方面的主要帮助。非常感谢作者Nitin Prabhu和Tim Mattison。
https://dzone.com/articles/spring-transaction-management
http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/
我希望这有助于某人!
答案 1 :(得分:2)
Spring Transaction Management
的默认行为是在发生检查的异常时提交。如果要回滚事务,可以抛出未经检查的异常(RuntimeException
)。 @Transactional(rollbackFor = Exception.class)
也会得到相同的结果。
请试一试。
感谢。
答案 2 :(得分:0)
根本原因是缺少事务管理器,因为我们明确地创建了数据源,而不依赖于Spring引导来根据application.yml
中的参数自动创建。
此外,不需要注释类而是注释下面的方法并在启动期间初始化事务管理器bean。
@Transactional(propagation = Propagation.REQUIRED, transactionManager = "transactionManager", rollbackFor = CustomExcp.class)
public int updt(Emp vo) throws CustomExcp {
...
}
@Bean
public DataSourceTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
log.info("DataSource Transaction Manager");
return transactionManager;
}