如何通过PlatformTransactionManager显式执行事务的开始、提交与回滚?
问题描述
我使用Spring的PlatformTransactionManager,搭配jTds驱动和Sybase ASE 16数据库。由于启用AutoCommit会触发SET CHAINED ON,但数据库里存在依赖非链式存储过程的触发器,因此无法开启AutoCommit。目前数据库连接已设置SET CHAINED OFF(即AutoCommit=false),但Sybase ASE要求必须显式执行begin transaction、commit transaction或rollback transaction,否则所有事务操作会被完全忽略。想让PlatformTransactionManager自动执行这些显式事务语句,是否可行?
更新:配置信息
application.properties配置
spring.sybase.url=jdbc:jtds:sybase://hostname:6000/db;autoCommit=false;appName=integration spring.sybase.username=myuser spring.sybase.password=mypass spring.sybase.driver-class-name=net.sourceforge.jtds.jdbc.Driver spring.sybase.hikari.pool-name=datasource-pool spring.sybase.hikari.connection-timeout=3000 spring.sybase.hikari.maximum-pool-size=5 spring.sybase.hikari.minimum-idle=0 spring.sybase.hikari.transaction-isolation=TRANSACTION_READ_COMMITTED spring.sybase.hikari.auto-commit=false spring.sybase.hikari.connection-test-query=SELECT 1
Bean配置
@Configuration @EnableTransactionManagement public class SybaseDataSourceConfig { public static final String SYBASE_JDBC_TEMPL = "sybaseJdbcTempl"; public static final String SYBASE_DS = "sybaseDs"; public static final String SYBASE_DS_PROPERTIES = "sybaseDsProp"; public static final String SYBASE_TRAN_MANAGER = "sybaseTM"; @Bean(name = SYBASE_DS_PROPERTIES) @ConfigurationProperties("spring.sybase") public DataSourceProperties sybaseDataSourceProperties() { return new DataSourceProperties(); } @Bean(name = SYBASE_DS) @ConfigurationProperties("spring.sybase.hikari") public HikariDataSource sybaseDataSource(@Qualifier(SYBASE_DS_PROPERTIES) final DataSourceProperties sybaseDataSourceProperties) { return sybaseDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); } @Bean(name = SYBASE_JDBC_TEMPL) public JdbcTemplate sybaseJdbcTemplate(@Qualifier(SYBASE_DS) final HikariDataSource sybaseDataSource) { return new JdbcTemplate(sybaseDataSource); } @Bean(name = SYBASE_TRAN_MANAGER) public PlatformTransactionManager transactionManager(@Qualifier(SYBASE_DS) final DataSource sybaseDataSource) { DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(sybaseDataSource); return dataSourceTransactionManager; } }
解决方案
完全可行,通过自定义DataSourceTransactionManager扩展类,就能让Spring事务管理器自动执行Sybase ASE要求的显式事务语句,具体实现如下:
自定义Sybase事务管理器
继承Spring的DataSourceTransactionManager,重写事务生命周期的核心方法,在对应阶段执行Sybase的显式事务命令:
public class SybaseTransactionManager extends DataSourceTransactionManager { private static final String BEGIN_TRANSACTION = "begin transaction"; private static final String COMMIT_TRANSACTION = "commit transaction"; private static final String ROLLBACK_TRANSACTION = "rollback transaction"; public SybaseTransactionManager(DataSource dataSource) { super(dataSource); } @Override protected void doBegin(Object transaction, TransactionDefinition definition) { super.doBegin(transaction, definition); // 获取当前事务绑定的连接,执行begin transaction Connection con = getConnectionHolder(transaction).getConnection(); try (Statement stmt = con.createStatement()) { stmt.execute(BEGIN_TRANSACTION); } catch (SQLException e) { throw new TransactionSystemException("执行Sybase begin transaction失败", e); } } @Override protected void doCommit(DefaultTransactionStatus status) { Connection con = getConnectionHolder(status.getTransaction()).getConnection(); try (Statement stmt = con.createStatement()) { stmt.execute(COMMIT_TRANSACTION); } catch (SQLException e) { throw new TransactionSystemException("执行Sybase commit transaction失败", e); } super.doCommit(status); } @Override protected void doRollback(DefaultTransactionStatus status) { Connection con = getConnectionHolder(status.getTransaction()).getConnection(); try (Statement stmt = con.createStatement()) { stmt.execute(ROLLBACK_TRANSACTION); } catch (SQLException e) { throw new TransactionSystemException("执行Sybase rollback transaction失败", e); } super.doRollback(status); } }
修改配置类中的事务管理器Bean
将原有的DataSourceTransactionManager替换为自定义的SybaseTransactionManager:
@Bean(name = SYBASE_TRAN_MANAGER) public PlatformTransactionManager transactionManager(@Qualifier(SYBASE_DS) final DataSource sybaseDataSource) { return new SybaseTransactionManager(sybaseDataSource); }
关键注意事项
- 调用父类方法的顺序:先执行
super.doBegin()等父类逻辑,再执行Sybase的显式事务命令,避免Spring事务的连接状态与自定义命令冲突。 - 测试验证:可通过开启JDBC日志(如
logging.level.net.sourceforge.jtds=DEBUG)查看实际执行的SQL语句,确认显式事务命令已触发;同时验证事务提交/回滚的逻辑是否符合预期。
内容的提问来源于stack exchange,提问作者Thiago Sayão
相关产品推荐
相关产品推荐

