Spring事务管理之几种方式实现事务
转自:https://blog.csdn.net/chinacr07/article/details/78817449
1、事务认识
大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销。Spring事务管理基于底层数据库本身的事务处理机制。数据库事务的基础,是掌握Spring事务管理的基础。这篇总结下Spring事务。
事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写
2、事务的传播特性
事务传播行为就是多个事务方法调用时,如何定义方法间事务的传播。Spring定义了7中传播行为:
(1)propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是Spring默认的选择。
(2)propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
(3)propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
(4)propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
(5)propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
(6)propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
(7)propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作
3、事务的隔离级别
(1)read uncommited:是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
(2)read commited:保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。
(3)repeatable read:这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。
(4)serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读
4、事务几种实现方式
(1)编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
(2)基于 TransactionProxyFactoryBean的声明式事务管理
(3)基于 @Transactional 的声明式事务管理
(4)基于Aspectj AOP配置事务
5、举例说明事务不同实现
编程式事务基本已经OUT了
声明式事务
基于 TransactionProxyFactoryBean的声明式事务管理
<!-- 事务管理器 --> <bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 事务代理工厂 --> <!-- 生成事务代理对象 --> <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="myTracnsactionManager"></property> <property name="target" ref="buyStockService"></property> <property name="transactionAttributes"> <props> <!-- 主要 key 是方法 ISOLATION_DEFAULT 事务的隔离级别 PROPAGATION_REQUIRED 传播行为 --> <prop key="add*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop> <!-- -Exception 表示发生指定异常回滚,+Exception 表示发生指定异常提交 --> <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException</prop> </props> </property> </bean>
基于 @Transactional 的声明式事务管理
public class BuyStockServiceImpl implements BuyStockService{ private AccountDao accountDao; private StockDao stockDao; @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED) @Override public void addAccount(String accountname, double money) { accountDao.addAccount(accountname,money); } @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED) @Override public void addStock(String stockname, int amount) { stockDao.addStock(stockname,amount); } public BuyStockServiceImpl() { // TODO Auto-generated constructor stub } @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,rollbackFor=BuyStockException.class) @Override public void buyStock(String accountname, double money, String stockname, int amount) throws BuyStockException { boolean isBuy = true; accountDao.updateAccount(accountname, money, isBuy); if(isBuy==true){ throw new BuyStockException("购买股票发生异常"); } stockDao.updateStock(stockname, amount, isBuy); } public AccountDao getAccountDao() { return accountDao; } public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public StockDao getStockDao() { return stockDao; } public void setStockDao(StockDao stockDao) { this.stockDao = stockDao; } }
<!-- 事务管理器 -->
<bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="myTracnsactionManager"/>
基于Aspectj AOP配置事务
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册数据源 C3P0 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <bean id="accountDao" class="transaction.test4.dao.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="stockDao" class="transaction.test4.dao.StockDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="buyStockService" class="transaction.test4.service.BuyStockServiceImpl"> <property name="accountDao" ref="accountDao"></property> <property name="stockDao" ref="stockDao"></property> </bean> <!-- 事务管理器 --> <bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:advice id="txAdvice" transaction-manager="myTracnsactionManager"> <tx:attributes> <!-- 为连接点指定事务属性 --> <tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="BuyStockException"/> </tx:attributes> </tx:advice> <aop:config> <!-- 切入点配置 --> <aop:pointcut expression="execution(* *..service.*.*(..))" id="point"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="point"/> </aop:config>