Home Articles

Spring Transaction Management无法使用Spring Boot MyBatis?

Asked
Viewed 899 times
3

我试图让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应用程序中手动完成并且不在其中的地方 - 我们能够进一步配置它 . 有了这个说我在我的_2797518中尝试了以下配置而没有运气:

<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 .

任何有助于我朝着正确方向前进的帮助或想法都将不胜感激 . 如果您需要任何进一步的信息,我很乐意提供!

提前致谢!

Xandel

3 Answers

  • 2

    所以我通过使用 @Transactional 而不是方法定义来注释类定义来实现它 .

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

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

    但是现在,我的问题已经解决了 .

    EDIT

    回到这个月的问题后,我终于找到了它的底部 . 这里有两个主要问题 .

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

    • “事务边界仅在通过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/

    我希望这有助于某人!

  • 1

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

    请试试这个 .

    有关详细信息,请参阅http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction-declarative-rolling-back

    谢谢 .

  • 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;
        }
    

Related