原生JDBC未使用JdbcTemplate时能否使用Spring @Transaction事务?
问题解答:不使用JdbcTemplate能否正常使用Spring声明式事务
完全可以正常使用,Spring声明式事务的核心逻辑和是否使用JdbcTemplate没有绑定关系。
底层原理说明
你配置的DataSourceTransactionManager(PlatformTransactionManager的JDBC实现类)的核心逻辑是:
- 事务开启时,从关联的DataSource获取一个连接
- 关闭连接的自动提交,将这个连接绑定到当前线程上下文
- 后续只要你从同一个DataSource对象调用
getConnection(),都会拿到这个已经绑定了事务的连接,不会新建独立连接 - 方法执行完成无异常时自动提交事务,抛出符合回滚规则的异常时自动回滚,最后释放连接
所以只要你的原生JDBC代码是从Spring管理的DataSource获取连接,就会自动加入Spring管理的事务,和你用不用JdbcTemplate没有任何区别。
迁移注意事项
- 必须使用Spring容器注入的DataSource获取Connection,不能手动创建JDBC连接,也不能使用独立于Spring的连接池获取连接,否则拿到的连接不受Spring事务管控
- 不要在业务代码中手动调用
Connection.commit()、Connection.rollback()、Connection.setAutoCommit(true)这类事务控制方法,所有事务控制逻辑全部由Spring事务管理器处理,你只需要通过@Transactional的参数(比如rollbackFor、传播属性等)配置规则即可,手动操作会打断Spring的事务流程 - 遵守
@Transactional的通用生效规则:只能标注在public方法上,且必须是Spring代理类外部调用该方法才会触发事务,同类内部非代理调用不会生效,这是Spring AOP的通用规则,和持久层实现无关
最小可运行示例
配置类
@Configuration @EnableTransactionManagement // 开启声明式事务注解支持 public class JdbcTransactionConfig { @Bean public DataSource dataSource() { HikariDataSource dataSource = new HikariDataSource(); // 自行配置数据源参数:jdbcUrl、username、password、driverClassName等 return dataSource; } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
业务类示例
@Service public class OriginalJdbcBizService { // 注入Spring管理的数据源 @Autowired private DataSource dataSource; @Transactional(rollbackFor = Exception.class) public void saveBizData() throws SQLException { // 直接从注入的DataSource获取连接,自动加入当前事务 try (Connection connection = dataSource.getConnection(); PreparedStatement ps = connection.prepareStatement("INSERT INTO user(name, age) VALUES (?, ?)")) { ps.setString(1, "张三"); ps.setInt(2, 25); ps.executeUpdate(); // 无需手动提交,方法正常执行结束Spring会自动提交 // 若此处抛出异常,Spring会自动回滚所有操作 } } }
你完全可以按计划逐步迁移,先将事务控制权交给Spring,保留原有原生JDBC业务逻辑不变,后续再按需迭代替换持久层实现即可,两者不存在冲突。
内容的提问来源于stack exchange,提问作者Kumar
相关产品推荐
相关产品推荐

