在SSM项目中,经常在业务层的类或者方法上看到@Transactional注解,只是知道这个注解的作用是进行事务管理,但是具体有哪些属性,在什么情况下进行回滚,确是不那么清楚。所以在网上看了一些视频和博客,初步理解了Spring的事务管理。这里记录的主要是一些概念,如果想要能快速学会使用和理解事务管理,建议去相关视频。我看的是https://www.imooc.com/learn/478

  一、要理解Spring的事务管理,首先要了解什么是事务,事务有哪些特性,不遵守这些特性会出现什么问题。只有了解这些,才会理解事务管理要做什么。

    1.事务:逻辑上的一组操作,这组操作要么全部成功,要么全部失败。

    2.事务的特性

     (1)原子性:事务是一个不可分割的工作单位,事务中的操作在提交后要么全部成功,要么全部失败。

     (2)一致性:事务提交前后的数据的完整性必须保持一致。

     (3)隔离性:多个事务之间不会产生相互干扰,事务间的数据要相互隔离。

     (4)持久性:事务一单被提交,它对数据库的改变将是永久的,即使数据库发生故障也不应对其产生影响。

    3.如果事务不遵守上述的特性,则会出现脏读、不可重复读和幻读的问题

    (1)脏读:一个事务读取一个另一个事务改写但是还未提交的数据。如果这些数据回滚,则第一个事务读取到的数据将是无效的。

    (2)不可重复读:在同一个事务中,多次读取同一个数据的结果有所不同。

    (3)幻读:在一个事务读取数据后,另一个事务插入一些记录。当再次查询时,第一个事务将会发现原来没有的记录。

  二、了解了这些基础概念之后,再去了解Spring为事务管理提供的接口。

    1.PlatformTransactionManager:平台事务管理器接口。Spring为不同的持久化框架提供了不同的实现,如为Spring JDBC或MyBatis提供了DataSourceTransactionManager,

      为Hibernate提供了HibernateTransactionManager。事务管理器中定义了一些具体的事务操作,如事务提交、事务回滚。

    2.TransactionDefinition:事务定义信息。如事务隔离级别、传播行为、超时和只读。

    (1)事务隔离级别

      a)READ_UNCOMMITTED:允许读取另一个事务修改了但是还未提交的数据,会出现脏读、不可重复读和幻读的情况

      b)READ_COMMITTED:允许在另一个事务提交后读取数据,可防止脏读,但是会出现不可重复读和幻读。

      c)REPEATABLE_READ:对相同的数据的读取是一致的,除非事务本身修改了数据。可防止脏读和不可重复读,会出现幻读。

      d)SERIALIZABLE:该隔离级别是完全遵守ACID隔离级别的,能够确保不会发生脏读、不可重复读和幻读。但是由于读取相同数据的事务是完全串行读取的,所以执行速度非常慢。

      e)DEAFULT:Spring默认使用该隔离级别。表示使用后端数据库的默认隔离级别,MySQL的默认隔级别是REPEATABLE_READ,ORACLE的默认隔离级别是READ_COMMITTED。

    (2)传播行为,用于解决业务层中多个方法调用的问题

      a)PROPAGATION_REQUIRED:支持当前事务。如果当前事务存在,将另一个事务添加到当前事务中;如果当前事务不存在,则创建一个新的事务,并将第一个包含进去。

      b)PROPAGATION_SUPPORTS:支持当前事务。如果当前事务不存在,则以非事务方式执行。

      c)PROPAGATION_MANADATORY:支持当前事务。如果当前事务不存在,抛出异常。

      d)PROPAGATION_REQUIRES_NEW:新建事务,挂起当前事务,新建事务完成后再执行当前事务。

      e)PROPAGATION_NOT_SUPPORTS:以非事务方式执行。如果存在当前事务,则挂起当前事务。另一个方法执行完成后再执行当前事务。

      f)PROPAGATION_NEVER:以非事务方式运行。如果存在当前事务,则抛出异常。

      g)PROPAGATION_NESTED:若当前事务存在,则将第二个事务嵌套到当前事务中。

    (3)超时:默认为-1。设置超时时间后事务还未完成,则回滚事务。

    (4)只读:指定事务为只读事务,默认false。如果设置为true,事务中存在新增、删除和修改数据库则会抛出异常并回滚。

    3.TransactionStatus:事务具体运行状态。

  三、配置事务管理

    1.编程式事务管理:通过在方法中编写事务管理程序来实现事务管理,这种方式对业务层代码有侵入,很少使用。

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.outMoney(out, money);
int i = 1 / 0;
accountDao.inMoney(in, money);
}
});

    

    2.声明式事务管理:

    (1)使用代理实现事务管理,需要为每一个类添加一个代理类,当需要事务管理的类增多时,添加代理类很麻烦。所以这个很少使用。

    <!--注入代理-->
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--注入目标对象-->
<property name="target" ref="declarativeAccountService" />
<!--注入事物管理器-->
<property name="transactionManager" ref="transactionManager" /> <property name="transactionAttributes">
<props>
<prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>
</props>
</property>
</bean>
    @Resource(name="accountServiceProxy")
private DeclarativeAccountService declarativeAccountService;

    

    (2)使用AspectJ实现事务管理,需要配置增强通知和切面。需要事务管理的包或类很清晰。

    <!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice> <aop:config>
<!--配置切入点-->
<aop:pointcut id="aspectJPoint" expression="execution(* imooc.spring.transaction.manage.service.AspectJAccountService+.*(..))" />
<!--配置切面-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="aspectJPoint" />
</aop:config>

    

    (3)基于注解的事务管理:需要的步骤有1.配置事务管理器,可以在xml中配置,同时也可以使用注解配置 2.在类或方法上标注@Transactional注解。

<tx:annotation-driven transaction-manager="transactionManager" />

  四、使用@Transactional注解需要注意的几点

    1.在类和方法上都可以标注@Transactional注解,同时在类或方法上标有@Transactional注解时,方法上的事务管理属性胡会覆盖类上的属性。

    2.@Transactional注解只有标注在public方法上时才会生效,标注在其它方法上不会报错,但是不能生效。

    3.默认情况下,事务中如果抛出未检查异常(RuntimeException或其子类)和ERROR时,事务将回滚;除此之外的异常将不会回滚。

      在阿里的p3c代码规范中要求在标注事务管理时添加rollbackFor属性,即@Transactional(rollbackFor=Exception.class)。

上述概念都是在看完博客和视频后的一些记录,如果有错误的地方欢迎指正。如果有兴趣的,可以查阅相关博客和视频链接如下:

https://www.cnblogs.com/xd502djj/p/10940627.html

https://www.imooc.com/learn/478

初步理解@Transactional注解的更多相关文章

  1. spring的事务解决方案之@Transactional注解

    首先此注解位于 org.springframework.transaction.annotation 这个包路径下面, 事务有两种类别,一种是编程式事务,另一种是声明式事务,显然此注解是声明式事务,这 ...

  2. 对于spring中事务@Transactional注解的理解

    现在spring的配置都喜欢用注解,这边就说下@Transactional 一.如何开启@Transactional支持 要使用@Transactional,spring的配置文件applicatio ...

  3. spring5 源码深度解析----- @Transactional注解的声明式事物介绍(100%理解事务)

    面的几个章节已经分析了spring基于@AspectJ的源码,那么接下来我们分析一下Aop的另一个重要功能,事物管理. 事务的介绍 1.数据库事物特性 原子性多个数据库操作是不可分割的,只有所有的操作 ...

  4. @RestController注解初步理解

    一.在Spring中@RestController的作用等同于@Controller + @ResponseBody. 所以想要理解@RestController注解就要先了解@Controller和 ...

  5. 数据库事务中的隔离级别和锁+spring Transactional注解

    数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...

  6. @Transactional注解*

    类或者方法加@Transactional注解 表示该类里面的所有方法或者这个方法的事务由spring处理,来保证事务的原子性,不知道这样说你能不能理解,即是方法里面对数据库操作,如果有一个方法操作失败 ...

  7. JPA中自定义的插入、更新、删除方法为什么要添加@Modifying注解和@Transactional注解?

    前几天,有个同事在使用JPA的自定义SQL方法时,程序一直报异常,捣鼓了半天也没能解决,咨询我的时候,我看了一眼他的程序,差不多是这个样子的: @Repository public interface ...

  8. springBoot(1)---springboot初步理解

    springboot初步理解 在没有用SpringBoot之前,我们用spring和springMVC框架,但是你要做很多比如: (1)配置web.xml,加载spring和spring mvc 2) ...

  9. Spring Boot 中使用 @Transactional 注解配置事务管理

    事务管理是应用系统开发中必不可少的一部分.Spring 为事务管理提供了丰富的功能支持.Spring 事务管理分为编程式和声明式的两种方式.编程式事务指的是通过编码方式实现事务:声明式事务基于 AOP ...

随机推荐

  1. CSRF原理及防御

    CSRF原理及防御 CSRF攻击原理 CSRF攻击利用网站对用户的信任,以用户的身份发送请求来执行攻击者所要的操作,比如:转账.发邮件.修改密码.添加用户等. CSRF和XSS一样危害都特别大,只不过 ...

  2. Python 读取Excel之xlrd篇

    上一期给大家分享了如何用Python读取文本,这次给大家分享如何读取Excel表格内容,拿最常见的.xlsx和.xls格式来讲解. 本章主要知识点有: 读取整篇excel返回list[list[lis ...

  3. Maven 专题(三):为什么要用Maven

    1 真的需要吗? Maven 是干什么用的?这是很多同学在刚开始接触 Maven 时最大的问题.之所以会提出这个问题, 是因为即使不使用 Maven 我们仍然可以进行 B/S 结构项目的开发.从表述层 ...

  4. redis必知会

    Redis 是单进程单线程的? Redis 是单进程单线程的,redis 利用队列技术将并发访问变为串行访问,消 除了传统数据库串行控制的开销. Redis 的持久化机制是什么?各自的优缺点? Red ...

  5. java 获取传入值的区间

    /** * 获取值的区间 * * @param num 值 */ public static Map<String, Integer> getNumSection(Integer num) ...

  6. PyQt5多线程和定时器

    多线程 一般情况单线程就可以很好的完成任务,但是对于GUI程序来说,单线程就不能完全满足需求.如果有耗时流程,在单线程的情况下,界面操作就会卡死,直到耗时操作完成,才会响应界面操作.为了解决这个问题, ...

  7. MySQL数据库---库的操作

    MySQL数据库中,以库,表,记录的形式管理所有的数据,安装MySQL数据库的服务器上可以包含多个库,一个库中包含多张表,一张表中包含多条记录.库对应的是文件系统中文件夹的概念,表对应的是文件的概念, ...

  8. shell脚本sql赋值

    以下脚本功能是用shell脚本登录sqlplus连接oracle,将执行sql语句查询的结果赋值给shell脚本中的变量 #!/bin/bash echo "开始连接数据库..." ...

  9. 重学数据结构(三)——使用单链表实现LRU淘汰缓存机制

    使用单链表实现LRU(Least Recently Used)淘汰缓存机制 需求:存在一个单链表,在单链表尾部的都是越早之前添加的元素. 当元素被访问到时,会添加进缓存(也就是这个单链表中). 如果这 ...

  10. 洛谷p1120小木棍(剪枝优化)

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...