使用MyBatis进行春季引导不会回滚事务

时间:2019-10-09 10:47:04

标签: spring-boot transactions mybatis spring-mybatis

我有一个Spring Boot(版本2.1.8.RELEASE)Web应用程序(部署在Wildfly 9应用程序容器中),带有MyBatis,它是通过Spring Boot启动程序自动配置的,但是使用{{1 }}注释,即使应回滚这些语句,它们也始终是提交的。我的pom.xml片段如下所示:

@transactional

在application.properties中有以下几行:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.0</version>
</dependency>

这是我的mybatis-config.xml

spring.datasource.url=jdbc:sqlserver://my.server.com:1433;databaseName=MyDatabase
spring.datasource.username=myUsername
spring.datasource.password=myPassword
mybatis.config-location=classpath:mybatis-config.xml

我的应用程序初始化程序类如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="localCacheScope" value="STATEMENT"/>
    </settings>
    <typeAliases>
        <package name="my.package.model"/>
    </typeAliases>
    <mappers>
    ...
    </mappers>
</configuration>

我有一个控制器,它不是事务的一部分,但是会自动连接到服务层bean中:

@SpringBootApplication
@EnableTransactionManagement
@ComponentScan("my.packag e")
public class ServletInitializer extends SpringBootServletInitializer
{
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) 
    {
        // some config here

        return builder.sources(ServletInitializer.class);
    } // end method configure()

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException
    {
        super.onStartup(servletContext);
        // some config here
    } // end method onStartup()

    // some other beans here

    public static void main(String[] args) 
    {
        SpringApplication.run(ServletInitializer.class, args);
    }

} // end class ServletInitializer

我的服务类别如下:

@Controller
public class DataMigrationController
{

    @AutoWired private MyService service;

    @GetMapping("/path")
    public @ResponseBody Boolean something(Model model, HttpSession session)
    {
        service.doTask();
        return true;
    }
}

由于@Service public class MyService { @AutoWired private MyMapper mapper; @Transactional(rollbackFor=Throwable.class) public void doTask() { Person p= new Person(); p.setPersonID("999999"); p.setSurname("TEST"); p.setForename1("TEST"); p.setTitle("Mr"); mapper.insertPerson(p); throw new RuntimeException(); } } 方法的末尾引发了RuntimeException,因此我希望事务能够回滚,但是当我检查数据库时,该行就出现了。我也尝试过使用doTask()而不是抛出异常,但是我得到了相同的结果。

我正在使用this blog post建议的事务调试类,该类告诉我控制器中没有事务(这是我期望的),服务类中有事务。但是由于某种原因,交易并没有回滚。

有人可以建议吗?

1 个答案:

答案 0 :(得分:1)

我找到了提交交易的原因。 Spring Boot默认使用Java EE(Jakarta EE)环境下的JTA事务管理。但是通过Spring Boot创建的DataSource无法加入。

您可以选择以下解决方案:

  • 禁用JTA事务管理
  • 使用由Wildfly管理的事务DataSource

如何禁用JTA事务管理

您可以按以下方式禁用JTA事务管理:

spring.jta.enabled=false

有关详细信息,请参见https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/htmlsingle/#boot-features-jta

如何使用由Wildfly管理的DataSource

您可以使用Wildfly管理的DataSource

spring.datasource.jndi-name=java:jboss/datasources/demo

有关详细信息,请参见https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/htmlsingle/#boot-features-connecting-to-a-jndi-datasource

注意:如何在Wildfly上配置DataSource(需要启用JTA),请参见https://docs.jboss.org/author/display/WFLY9/DataSource+configuration?_sscc=t