事务的特性:一致性、原子性、隔离性、持久性
Spring事务管理相关接口:PlatformTransactionManager(事务管理器)、TransactionDefinition(事务定义信息,隔离、传播、超时、只读)、TransactionStatus(事务具体运行状态)
1、事务管理器
相关的PlatformTransactionManager接口
2、事务隔离级别
当不考虑隔离性会引起一下问题:
(1)脏读:一个事务读取了另一个事务改写但未提交的数据,如果这些数据被回滚则读到的数据是无效的。A进行update、insert时候,B读取了中间状态不知道对不对的值。
(2)不可重复读:在同一事务中,多次读取同一数据返回的结果不同。B在A 的update操作前后,读到的数据不一致。
(3)幻读:一个事务读取了几行记录后,另一个事务插入一些记录,再后来查询中第一个事务就会发现有些原来没有的记录。B在A的insert操作前后,读到了的数据不一致。
事务的四种隔离级别,Mysql默认使用REPEATABLE_READ隔离级别,orcale默认使用READ_COMMOTTED
3、事务传播行为
事务传播行为:解决业务层方法之间的相互调用的问题
七种事务传播行为,其中分为三类。
第一类:PROPAGATION_REQUIRED(重点)、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY
第二类:PROPAGATION_REQUIRES_NEW(重点)、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER
第三类:PROPAGATION_NESTED(重点)
4、Spring事务管理的实现方式
(1)编码式事务管理:
手动编写代码进行事务管理(很少使用)
(2)声明式事务管理:
基于TransactionProxyFactoryBean的方式(很少使用):需要为每一个进行事务管理的类,配置一个TransactionProxyFactoryBean进行增强。
基于AspectJ的XML方式(经常使用):一旦配置好后,类不需要加任何东西。
基于注解的方式(经常使用):配置简单,需要在业务层类上或方法上加上一个注解@Transactional。
1、 手动编写代码进行事务管理
applicationContext.xml文件。(主要transactionManager和transactionTemplate)
<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="cn.muke.spring.demo1.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> bean> <bean id="accountService" class="cn.muke.spring.demo1.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="transactionTemplate" ref="transactionTemplate" /> bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> bean> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> bean>
业务类
实现transactionTemplate的execute
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
private TransactionTemplate transactionTemplate;
@Override
public void transfer(final String out, final String in, Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.outMoney(out, money);
int i = 1/0;
accountDao.inMoney(in, money);
}
});
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
}
2、基于TransactionProxyFactoryBean的方式
applicationContext.xml(需要为每个类配置TransactionProxyFactoryBean)
<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="cn.muke.spring.demo2.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> bean> <bean id="accountService" class="cn.muke.spring.demo2.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> bean> <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="target" ref="accountService"/> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributes"> <props> <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticExceptionprop> props> property> bean>
业务层(不需做任何代码改动)
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Override
public void transfer(String out, String in, Double money) {
accountDao.outMoney(out, money);
int i = 1 / 0;
accountDao.inMoney(in, money);
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
3、基于AspectJ的XML方式
applicationContext.xml(txAdvice,切面编程)
<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="cn.muke.spring.demo3.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> bean> <bean id="accountService" class="cn.muke.spring.demo3.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource">property> bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="transfer" propagation="REQUIRED" no-rollback-for="java.lang.ArithmeticException" /> tx:attributes> tx:advice> <aop:config> <aop:pointcut expression="execution(* cn.muke.spring.demo3.AccountService+.*(..))" id="pointcut1"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/> aop:config>
业务层(不需做任何代码改动)
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Override
public void transfer(String out, String in, Double money) {
accountDao.outMoney(out, money);
int i = 1 / 0;
accountDao.inMoney(in, money);
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
4、基于注解的方式
applicationContext.xml(开启注解事务)
<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="cn.muke.spring.demo4.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> bean> <bean id="accountService" class="cn.muke.spring.demo4.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource">property> bean> <tx:annotation-driven transaction-manager="transactionManager"/>
业务层(增加注解@Transactional)
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
/**
* propagation :事务的传播行为
* isolation :事务的隔离级别
* readOnly :只读
* noRollbackFor :发生哪些异常事务不回滚
* noRollbackForClassName :发生哪些异常事务不回滚
* rollbackFor :发生哪些异常回滚事务
* rollbackForClassName :发生哪些异常回滚事务
*/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void transfer(String out, String in, Double money) {
accountDao.outMoney(out, money);
try {
int i = 1 / 0;
} catch (Exception e) {
throw new RuntimeException();
}
accountDao.inMoney(in, money);
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
项目代码在文件中
Original: https://www.cnblogs.com/maple92/p/8612938.html
Author: Topze
Title: Spring事务管理
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/582950/
转载文章受原作者版权保护。转载请注明原作者出处!