常见问题解决方案 (Solutions to Common Problems)
本节描述了一些常见问题的解决方案。
为特定 DataSource 使用错误的事务管理器
请根据你选择的事务技术和需求,使用正确的 PlatformTransactionManager 实现。如果使用得当,Spring 框架仅仅提供了一个简单且可移植的抽象。如果你使用全局事务,则必须对所有事务操作使用 org.springframework.transaction.jta.JtaTransactionManager 类(或其应用服务器特定的子类)。否则,事务基础设施会尝试在容器 DataSource 实例等资源上执行本地事务。此类本地事务是没有意义的,好的应用服务器会将它们视为错误。
补充教学
1. 为什么“本地事务”在 JTA 数据源上是错误的?
这是一个非常典型的错误场景,常见于将应用部署到 WebLogic、WebSphere 或 JBoss 等传统应用服务器时。
- 场景:你在应用服务器中配置了一个 JNDI 数据源,这个数据源是受容器管理的(Managed DataSource),参与 JTA 全局事务。
- 错误配置:你在 Spring 中配置了
DataSourceTransactionManager(适用于本地事务)。 - 后果:
- Spring 的
DataSourceTransactionManager获取连接。 - Spring 试图调用
connection.setAutoCommit(false)或connection.commit()。 - 崩溃:应用服务器会抛出异常(如
SQLException: You cannot commit during a managed transaction)。因为在 JTA 模式下,底层连接的提交/回滚权在事务协调器(Transaction Coordinator)手中,严禁应用层代码越俎代庖去直接操作连接。
- Spring 的
2. Spring Boot 的自动救赎
在现代 Spring Boot 开发中,这个问题很少出现,因为 Spring Boot 的自动配置(Auto-Configuration)非常智能:
- 它会检测 Classpath 下是否有 JTA 实现库(如 Atomikos, Bitronix)或是否运行在 Jakarta EE 容器中。
- 如果有,它会自动配置
JtaTransactionManager。 - 如果没有,它默认配置
DataSourceTransactionManager。
除非你手动覆盖了默认配置,否则通常不会遇到这个“张冠李戴”的问题。