1)事务的4个特性:原子性 一致性 隔离性 持久性
Spring 事务的默认回滚方式是:发生运行时异常和 error 时回滚,发生受查(编译)异常时 提交。
2)事务隔离级别 :
读未提交 :能够读取到没有被提交的数据;
读已提交 :即能够读到那些已经提交的数据,自然能够防止脏读,但是无法限制不可重复读和幻读;
可重复读:读取了一条数据,这个事务不结束,别的事务就不可以改这条记录;
串行化:最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务;
3)事务的并发问题:
脏读:一个事务读取了另一个事务尚未提交的数据
eg:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
不可重复读:一个事务的操作导致另一个事务前后两次读取到不同的数据
eg:当B事务select读取数据后,A事务update操作更改B事务select到的数据,此时B事务再次读去该数据,发现前后两次的数据不一样。
幻读: 一个事务的操作导致另一个事务前后两次查询的结果数据量不同。
eg:当B事务select读取数据后,A事务insert或delete了一条满足A事务的select条件的记录,此时B事务再次select,发现查询到前次不存在的记录(“幻影”),或者前次的某个记录不见了。
4) spring定义了五个事务隔离级别常量:
一个默认(默认的隔离级别是采用 DB 默认的事务隔离级别。MySql 的默认为可重复读( REPEATABLE_READ); Oracle 默认为读已提交 ( READ_COMMITTED))
四个与mysql的隔离级别一致
5)使用 Spring 的事务注解管理事务
通过@Transactional 注解方式,可将事务织入到相应 public 方法中,实现事务管理。
@Transactional 的所有可选属性如下所示:
需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非 public方法,如果加上了注解@Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该方法中。因为Spring 会忽略掉所有非 public 方法上的@Transaction 注解。
若@Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。
****适合中小项目使用的, 注解方案。
spring框架自己用aop实现给业务方法增加事务的功能, 使用@Transactional注解增加事务。@Transactional注解是spring框架自己注解,放在public方法的上面,表示当前方法具有事务。可以给注解的属性赋值,表示具体的隔离级别,传播行为,异常信息等等
使用@Transactional的步骤:
1)、 声明事务管理器
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
2).开启事务注解驱动, 告诉spring框架,要使用注解的方式管理事务。spring使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务的功能。spring给业务方法加入事务:在你的业务方法执行之前,先开启事务,在业务方法之后提交或回滚事务,使用aop的环绕通知
<tx:annotation-driven transaction-manager="transactionManager"/>
//transaction-manager:事务管理器 bean 的 id
@Around("你要增加的事务功能的业务方法名称")
Object myAround(){
//开启事务,spring给开启,相当于:
try{
buy(1001,10);
spring的事务管理器.commit();
}catch(Exception e){
spring的事务管理器.rollback();
}
}
3).在public公共方法的上面加入
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = {NotEnoughGoodsExceptipn.class,
NullPointerException.class})
public void buy(Integer goodsId, Integer amount) {
......
}
6)使用 AspectJ 的AOP 配置管理事务
适合大型项目,有很多的类,方法,需要大量的配置事务,使用aspectj框架功能,在spring配置文件中声明类,方法需要的事务。这种方式业务方法和事务配置完全分离。
使用 XML 配置事务代理的方式的不足是,每个目标类都需要配置事务代理。当目标类较多,配置文件会变得非常臃肿。
使用 XML 配置顾问方式可以自动为每个符合切入点表达式的类生成事务代理。其用法很简单,只需将前面代码中关于事务代理的配置删除,再替换为如下内容即可。
1、在容器中添加事务管理器
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2、配置事务通知
为事务通知设置相关属性。用于指定要将事务以什么方式织入给哪些方法。
例如,应用到 buy 方法上的事务要求是必须的,且当 buy 方法发生异常后要回滚业务。
<!--事务通知(切面)--> <tx:advice id="buyAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT" rollback-for="java.lang.NullPointerException, org.example.exception.NotEnoughGoodsExceptipn"/> <tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT" </tx:attributes> </tx:advice>
3、配置增强器
指定将配置好的事务通知,织入给谁.
<aop:config> <aop:pointcut expression="execution(* *..service..*.*(..))" id="servicePt"/> <!--声明增强器:通知和切入点的组合--> <aop:advisor advice-ref="buyAdvice" pointcut-ref="servicePt"/> </aop:config>
原文:https://www.cnblogs.com/8ling1ling/p/14379249.html