【问题标题】:Spring Transaction Management not working with Spring Boot + MyBatis?Spring 事务管理不能与 Spring Boot + MyBatis 一起使用?
【发布时间】:2016-09-15 14:03:33
【问题描述】:

我正在尝试让 Spring Transaction Management 在我的新 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")

我的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 映射器的 SqlSession 使用的相同 DataSource。

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

提前致谢!

山德尔

【问题讨论】:

  • 注释私有方法没有任何好处。见stackoverflow.com/q/7085271/217324
  • 已编辑问题 - 我可以通过公共方法确认问题仍然存在。
  • 默认情况下,检查异常不会导致回滚。
  • 你也可以发布插入方法代码吗?您是使用sqlSession 插入还是仅使用@Insert 映射器注释?如果您使用sqlSession,请发布有关如何创建对象的相关代码。当我开始研究 mybatis 时,同样的方法也适用于我。我只在方法级别使用了@Transactional
  • 我正在使用 mybator 生成的映射器,它创建映射器接口(无注释)和一个包含插入/更新 sql 查询的匹配 sql 映射器文件。 SqlSession 由 Spring 自动连接。

标签: java transactions spring-boot mybatis


【解决方案1】:

Spring Transaction Management 的默认行为是在发生检查异常时提交。如果要回滚事务,可以抛出未经检查的异常(RuntimeException)。 @Transactional(rollbackFor = Exception.class) 也给出了相同的结果。

请试试这个。

详情见https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-declarative-rolling-back

谢谢。

【讨论】:

    【解决方案2】:

    根本原因是缺少事务管理器,因为我们明确创建数据源,而不是依赖 Spring Boot 根据来自 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;
        }
    

    【讨论】:

      【解决方案3】:

      所以我通过使用 @Transactional 而不是方法定义来注释类定义来让它工作。

      我不确定这是否是常见做法。 Spring Boot Transaction Management 文档没有这样做 here,但 Mybatis Spring 示例在他们的文档 here 中确实这样做了...

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

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

      编辑

      一个月后回到这个问题,我终于明白了。这里有两个主要问题。

      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/

      我希望这对某人有帮助!

      【讨论】:

        猜你喜欢
        • 2016-11-07
        • 2018-09-10
        • 2017-05-29
        • 2020-02-06
        • 1970-01-01
        • 1970-01-01
        • 2018-12-25
        • 2020-03-16
        • 2016-12-27
        相关资源
        最近更新 更多