当前位置: 首页 > 知识库问答 >
问题:

Spring Transaction Management不适用于Spring Boot MyBatis?

翟弘
2023-03-14

我正在尝试让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")

我的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应用程序中手动完成的那样进行连接,如果没有,我们可以进一步配置它。话虽如此,我已经在我的应用程序上下文中尝试了以下配置。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映射器的Sql会话使用的相同的数据源。

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

提前感谢!

Xandel公司

共有3个答案

羊舌新荣
2023-03-14

根本原因是,对于我们显式创建数据源而不是依赖spring boot根据应用程序的参数自动创建的情况,缺少事务管理器。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;
    }
金飞翼
2023-03-14

Spring事务管理的默认行为是在发生选中的异常时提交。如果要回滚事务,可以抛出未经检查的异常(RuntimeException)。此外,事务(rollbackor=Exception.class)也给出了相同的结果。

请试试这个。

有关详细信息,请参阅https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-声明性回滚

谢谢。

澹台奇略
2023-03-14

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

我不确定这是否是惯例。Spring启动事务管理文档在这里并不是这样做的,但Mybatis Spring示例在这里的文档中确实是这样做的。。。

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

然而现在,我的问题解决了。

编辑

一个月后再回到这个问题上来,我终于找到了问题的根源。这里有两个主要问题。

>

  • 正如Kazuki正确提到的那样,您需要使用事务(rollback=Exception.class)注释明确声明需要对选中的异常进行回滚。

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

    在我的示例代码中,我调用了这个。从同一个类执行TransactionTest()。这样,事务将被忽略。如果我改为通过对我的类的有线引用调用它,例如myAutoWiredBean。performTransactionTest()一切正常。这也解释了为什么看起来只有类级注释在工作,但那是因为调用的任何方法都会被有线bean引用。

    这里有两篇文章,它们对我理解Spring事务管理的更精细细节有很大帮助。非常感谢作者尼廷·普拉布和蒂姆·马蒂森。

    https://dzone.com/articles/spring-transaction-management

    http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/

    我希望这对别人有帮助!

  •  类似资料:
    • 问题内容: 嗨,我只是简单地尝试在www.example.com上获取h1标签,该标签显示为“ Example Domain”。该代码适用于http://www.example.com,但不适用于https://www.exmaple.com。我该如何解决这个问题?谢谢 问题答案: PhantomJSDriver不支持(所有)DesiredCapabilities。 你会需要: 记录在这里:htt

    • 所以我使用这种方法写入文件,它在windows上运行完全正常,但在mac上运行时,它会创建文件,但它们是空的。 我知道数据是正确的,因为它打印正确。感谢您的任何帮助,这真的让我绊倒了。

    • 列名称的类型为int[] 上述查询适用于postgresql,但不适用于hsqldb,甚至适用于sql 尝试的hsqldb版本:2.2.9和2.3.0 在hsqldb中工作的sql是从table_name中选择x,unnest(column_name)y(x)x和y不是该表的列。

    • 我能够成功地打电话给邮递员: /mfp/api/az/v1/token和 /mfpadmin/management-apis/2.0/runtimes/mfp/applications 我正在获取从/mfp/api/az/v1/token接收的承载令牌,并将其添加到/mfp/applications的授权标头中。 我收到了来自两者的200个响应,并从每个API中获取了预期的信息。 然后,我选择从P

    • 我一直在使用声纳3.2 同样的配置,当我升级到SonarQube 4.4时 声纳项目属性: 请帮助整理这些例外 问候, KP

    • 我已经看过并尝试了几乎所有关于这个话题的其他帖子,但运气不好。 我使用的是python 3.6,所以我使用的是以下AMI

    • 问题内容: 我正在尝试制作一个游戏引擎。我已经制作了Game类,但错误仍在KeyBoard类中。在这里我留下一些代码。 类别::游戏 类::键盘 类别:: KeyTest 但是错误是没有抛出异常并且输入没有被读取。谁能说我这样做的正确方法。 问题答案: 简而言之,您的面板需要专注。在创建面板的任何地方添加: 这是一个SSCCE(我建议以后再问其中一个问题): 另外,https://www.goog

    • 我得到了这个: (节点:5496)未处理的promise拒绝警告:未处理的promise拒绝(拒绝ID:2):TypeError:无法读取null的prope rty'map' (节点:5496)[DEP0018]不推荐警告:不推荐未经处理的promise拒绝。将来,未处理的拒绝promise将终止节点。js进程的非零退出代码。 每次我运行我的“用户信息”命令时