Spring 事务管理不适用于 Spring Boot + MyBatis?

Xan*_*del 6 java transactions mybatis spring-boot

我正在尝试让 Spring 事务管理在我的新 Spring Boot + MyBatis 应用程序中工作。

到目前为止,我已经设法让一切都以最少的问题工作 - 它只是让@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")
Run Code Online (Sandbox Code Playgroud)

我的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
Run Code Online (Sandbox Code Playgroud)

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!");

}
Run Code Online (Sandbox Code Playgroud)

异常被抛出,但记录已经被插入。

目前基本上没有关于 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>
Run Code Online (Sandbox Code Playgroud)

我可以确认,即使没有上述任何配置,DataSourceTransactionManager 配置的数据源与 MyBatis 映射器的 SqlSession 使用的数据源相同。

任何可以将我推向正确方向的帮助或想法将不胜感激。如果您需要任何进一步的信息,我很乐意提供!

提前致谢!

山德尔

Xan*_*del 5

@Transactional因此,我通过注释类定义而不是方法定义来使其工作。

我不确定这是否是常见做法。Spring Boot 事务管理文档在这里没有这样做,但是 Mybatis Spring 示例在他们的文档确实这样做了......

如果有人有进一步的信息可以解释这一点,我会很乐意将该答案标记为正确的答案。

不过现在我的问题已经解决了。

编辑

一个月后回到这个问题我终于弄清楚了。这里有两个主要问题。

  1. 正如 Kazuki 正确提到的那样,您需要使用@Transactional(rollbackFor = Exception.class)注释明确声明需要对已检查的异常进行回滚。

  2. “仅当通过 Spring 代理调用正确注释的方法时才会创建事务边界。这意味着您需要通过 @Autowired bean 直接调用带注释的方法,否则事务将永远不会启动。” (参考下面这个来源)

在我的示例代码中,我是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/

我希望这对某人有帮助!