事务管理可以分为编程式事务管理和声明式事务管理。
声明式事务管理:声明式编程的事务管理方式,通过响应的配置,告诉让框架来我们需要达到什么样的效果,让框架来管理事务,而不需要使用者手动管理;
编程式事务管理 手动编写 不使用框架,纯粹开发者自己编写,可以使用Connection接口的commit,rollback方法,自行判断异常等逻辑进行手动事务管理;
Spring 事务模板 纯粹的开发自己编写,会存在大量的样板代码,比如Connection,statement的关闭等;Spring 提供和很多模板代码,可以解决这些问题,其中
Spring 内部封装了一个事务管理的TransactionTemplate模板类,其内部的transactionManager专门负责事务管理,其最终也是调用Connection的commit,rollback方法进行事务管理;
下面的代码用到了Spring 依赖注入,注入了一个TransactionTemplate的实例;要执行的数据库操作,都在模板类中执行;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class AccountServiceImplPragram implements AccountService {     private AccountDao accountDao;     private TransactionTemplate transactionTemplate;     public void transfer(final String out, final String in, final Double money) {         transactionTemplate.execute(new TransactionCallbackWithoutResult() {             @Override             protected void doInTransactionWithoutResult(TransactionStatus status) {                 accountDao.inMoney(in, money); //                int i = 1 / 0;                 accountDao.outMoney(out, money);             }         });     }     public void setAccountDao(AccountDao accountDao) {         this.accountDao = accountDao;     }     public void setTransactionTemplate(TransactionTemplate transactionTemplate) {         this.transactionTemplate = transactionTemplate;     } } 
声明式事务管理 即使Spring 提供了事务管理的模板,当时事务管理还是有点繁琐,而且这种事务管理方式有一定的侵入性;
能否有一种方式,可以让Service只是普通的Service,在调用DAO层的时候无需关心其事务问题;
有! Spring 提供了如下三中方式,解决这个问题,其中基于注解的方式,和基于AspectJ xml,虽然还是有一定的侵入性,但是这种方式极其简单,是日常开发常用的事务管理方式;
基于TransactionProxyFactoryBean代理的方式,使用不方便,而且还具有侵入性,通常不使用;
基于 TransactionProxyFactoryBean代理的Service方式事务管理 这种基于 TransactionProxyFactoryBean代理的Service方式,每次增加一个Service就必须增加一个相对的TransactionProxyFactoryBean用于增强对应的Service类,使用起来不方便;然后将这个TransactionProxyFactoryBean注入到Controller中,具有侵入性;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:springconfig_statement1.xml") public class TestTransactionManagerStatement1 {     @Resource(name = "transactionProxyFactoryBean")     private AccountService accountService;     @Test     public void testTransactionManagerStatement1() {         accountService.transfer("aaa", "bbb", 200d);     } }    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">         <property name="dataSource" ref="dataSource"/>    </bean>    <bean id="transactionProxyFactoryBean"           class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">         <!--配置注入要增强的类-->         <property name="target" ref="accountService"/>         <!--配置注入transactionManager-->         <property name="transactionManager" ref="transactionManager"/>         <property name="transactionAttributes">             <props>                 <!--key 可以是 instert update transfer -->                 <!--value 格式                 PROPAGATION:事务的传播级别                 ISOLATION :事务的隔离级别                 readOnly : 只读 (不可以进行 instert  update delete)                 -Exception  : 发生哪些异常执行回滚                 +Exception  : 发生哪些异常 不执行回滚                  <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>                 -->                 <prop key="transfer">PROPAGATION_REQUIRED</prop>             </props>         </property>     </bean> 
基于AspectJ xml 配置声明式的事务管理 通过Spring AOP 织入的方式给需要添加事务管理的方法增加事务管理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:springconfig_statement2.xml") public class TestTransactionManagerStatement2 {     @Resource(name = "accountService")     private AccountService accountService;     @Test     public void testTransactionManagerStatement2() {         accountService.transfer("aaa", "bbb", 200d);     } }  <tx:advice id="txAdvice" transaction-manager="transactionManager">         <tx:attributes>             <tx:method name="transfer"                        propagation="REQUIRED"             />         </tx:attributes>     </tx:advice>     <aop:config>         <aop:pointcut id="pointcut1"                       expression="execution(* com.conan.springtransaction.service.AccountService.transfer(..))"/>     </aop:config>     <aop:config>         <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>     </aop:config>           
基于注解方式的声明式事务管理 如下代码Spring是采用xml的配置方式,如果采用Java config配置方式,会更加简洁,只需要关注Service类上的@Transactional就好;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:springconfig_statement3.xml") public class TestTransactionManagerStatement3 {     @Resource(name = "accountService")     private AccountService accountService;     @Test     public void testTransactionManagerStatement3() {         accountService.transfer("aaa", "bbb", 200d);     } } @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImplStatement3 implements AccountService {     private AccountDaoImplStatement1 accountDao;     public void transfer(String out, String in, Double money) {         accountDao.inMoney(in, money);         int i = 1 / 0;         accountDao.outMoney(out, money);     }     public void setAccountDao(AccountDaoImplStatement1 accountDao) {         this.accountDao = accountDao;     } }   <!--引入实现文件-->     <context:property-placeholder location="classpath:jdbc.properties"/>     <!--C3P0 连接池-->     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">         <property name="driverClass" value="${jdbc.driverClass}"/>         <property name="jdbcUrl" value="${jdbc.url}"/>         <property name="user" value="${jdbc.username}"/>         <property name="password" value="${jdbc.password}"/>     </bean>     <bean id="accountDao" class="com.conan.springtransaction.dao.AccountDaoImplStatement1">         <property name="dataSource" ref="dataSource"/>     </bean>     <bean id="accountService" class="com.conan.springtransaction.service.AccountServiceImplStatement3">         <property name="accountDao" ref="accountDao"/>     </bean>     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">         <property name="dataSource" ref="dataSource"/>     </bean>     <tx:annotation-driven transaction-manager="transactionManager"/> //激活注解      
GitHub登录不了 ?信任该网站之后再登录。