spring事務管理包含兩種狀況,編程式事務、聲明式事務。而聲明式事務又包括基於註解@Transactional和tx+aop的方式。那麼本文先分析編程式註解事務和基於註解的聲明式事務。 編程式事務管理使用TransactionTemplate或者PlatformTransactionManager。對於編程式事務spring推薦使用TransactionTemplate。html
spring事務特性java
spring中全部的事務策略類都繼承自org.springframework.transaction.PlatformTransactionManager接口spring
public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }
編程式事務TransactionTemplate須要手動在代碼中處理事務,通常不推薦使用,也不符合spring的思想,由於它直接耦合代碼,但各有利弊。先看下TransactionTemplate的源碼。數據庫
public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean { protected final Log logger = LogFactory.getLog(getClass()); private PlatformTransactionManager transactionManager; public TransactionTemplate() { } public TransactionTemplate(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) { super(transactionDefinition); this.transactionManager = transactionManager; } public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } public PlatformTransactionManager getTransactionManager() { return this.transactionManager; } @Override public void afterPropertiesSet() { if (this.transactionManager == null) { throw new IllegalArgumentException("Property 'transactionManager' is required"); } } @Override public <T> T execute(TransactionCallback<T> action) throws TransactionException { if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) { return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action); } else { TransactionStatus status = this.transactionManager.getTransaction(this); T result; try { result = action.doInTransaction(status); } catch (RuntimeException ex) { // Transactional code threw application exception -> rollback rollbackOnException(status, ex); throw ex; } catch (Error err) { // Transactional code threw error -> rollback rollbackOnException(status, err); throw err; } catch (Throwable ex) { // Transactional code threw unexpected exception -> rollback rollbackOnException(status, ex); throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception"); } this.transactionManager.commit(status); return result; } } private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException { logger.debug("Initiating transaction rollback on application exception", ex); try { this.transactionManager.rollback(status); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by rollback error", ex); throw err; } } }
從上面的代碼能夠看到核心方法是execute,該方法入參TransactionCallback<T>。查看TransactionCallback源碼:編程
public interface TransactionCallback<T> { T doInTransaction(TransactionStatus status); }
那麼以上兩個源碼能夠肯定咱們使用編程式事務管理的方式也就是本身須要重寫doInTransaction()。OK,那麼咱們手動使用TransactionTemplate處理下。mvc
一、先配置transactionmanagerapp
<!--事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
二、配置transactionTemplateide
<!--編程式事務,推薦使用TransactionTemplate--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean>
三、業務代碼處理ui
@Autowired private TransactionTemplate transactionTemplate; public int insertUser2(final User user) { Integer i= (Integer) this.transactionTemplate.execute(new TransactionCallback() { public Object doInTransaction(TransactionStatus transactionStatus) { int i = userMapper.insertUser(user); if (i > 0) { System.out.println("success"); } int j = 10 / 0; return i; } }); return i; }
業務代碼中咱們使用by zero的異常故意拋出,你會發現能繼續打印success,當你斷點debug時,你會發現數據庫一直是鎖定狀態,直到你程序執行完。以下圖:this
2、基於Transactional註解的事務管理
當前應該是使用最清爽的事務管理方式了,也符合spring的理念,非入侵代碼的方式。
一、配置
<!--事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 使用註解事務,須要添加Transactional註解屬性 --> <tx:annotation-driven transaction-manager="transactionManager"/> <!--啓用最新的註解器、映射器--> <mvc:annotation-driven/>
二、配置後只須要在要處理的地方加上Transactional註解,並且Transactional註解的方式能夠應用在類上,也能夠應用在方法上,固然只針對public方法。
三、業務代碼處理
@Transactional public int insertUser(User user) { int i = userMapper.insertUser(user); if (i > 0) { System.out.println("success"); } int j = 10 / 0; return i; }