使用Spring BatchSqlUpdate时是否需禁用自动提交及实现方法
我们的项目是基于Spring与MSSQL JDBC驱动开发的老项目,通过applicationContext.xml配置了数据源事务管理器及方法代理。目前改用Spring的BatchSqlUpdate实现批量更新,已看到一定性能提升,但根据资料,批量操作需禁用自动提交才能发挥最大优势。我们的连接默认autocommit=true,适用于其他业务方法,但不清楚针对批量操作的特定方法/类,是否需要禁用自动提交、如何实现,同时还有两个疑问:手动获取连接禁用自动提交并使用PreparedStatement实现批量更新的方式是否比BatchSqlUpdate更快?BatchSqlUpdate能否禁用自动提交?
现有配置如下:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"><ref local="dataSource"/></property> </bean> <bean id="userManagerDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"><ref local="transactionManager"/></property> <property name="target"><ref bean="userManagerDAO"/></property> <property name="transactionAttributes"> <props> <prop key="get*">PROPAGATION_SUPPORTS</prop> <prop key="find*">PROPAGATION_SUPPORTS</prop> <prop key="is*">PROPAGATION_SUPPORTS</prop> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean>
数据源来自Wildfly的standalone.xml,原有更新方法继承SqlUpdate,改为继承BatchSqlUpdate并设置setBatchSize(1000)后可正常运行。
问题解答
1. BatchSqlUpdate是否需要手动禁用自动提交?
不需要。你的批量更新方法会匹配事务配置中的*规则,事务传播属性为PROPAGATION_REQUIRED。当该方法执行时,Spring的事务管理器会自动将当前连接的autocommit设为false,待批量操作全部执行完成后统一提交事务。BatchSqlUpdate作为Spring JDBC的抽象组件,会自动复用事务上下文内的连接,无需单独配置禁用自动提交。
2. 手动PreparedStatement方式与BatchSqlUpdate的性能对比
两者底层均依赖JDBC的批量更新API,性能几乎无差异。BatchSqlUpdate已经封装了连接管理、批量提交、资源回收等逻辑,不仅符合Spring的声明式事务规范,还能避免手动操作连接可能导致的资源泄漏问题。手动方式既没有性能优势,又增加了代码维护成本,完全没有必要替换现有实现。
3. 针对批量方法的事务配置优化(可选)
如果需要给批量更新方法单独配置更精细的事务属性(比如指定隔离级别、只读属性),可以在transactionAttributes中新增匹配规则,示例如下:
<props> <prop key="get*">PROPAGATION_SUPPORTS</prop> <prop key="find*">PROPAGATION_SUPPORTS</prop> <prop key="is*">PROPAGATION_SUPPORTS</prop> <prop key="batchUpdate*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED</prop> <prop key="*">PROPAGATION_REQUIRED</prop> </props>
该配置会让所有以batchUpdate开头的方法使用指定的事务属性,确保批量操作在最优的事务环境下执行。
内容的提问来源于stack exchange,提问作者user4746968

