事务的概念

在开发SSH项目中,我们把Service层类添加了注解 @Transactional,这个是用于设置事务的。当我们调用Service层的这个类的方法时,它能够保证我们的这个方法中执行的所有的对数据库的更新操作保持在一个事务中,在事务层里面调用的这些方法要么全部成功,要么全部失败。首先,我们要了解一些事务的ACID属性。

事务ACID属性(4)

A(Atomicity)——原子性

在一个事务上下文里面,对数据库进行的任何操作,必须保证是原子的,要么做,要么不做,不能出现只做一部分。比如我用支付宝给朋友转账的时候,要我这边需要减钱,朋友那边需要加钱,不能出现我方减钱,他方没有收到钱的情况。

C(Consistency)——一致性

一致性是指事务使得系统从一个一致的状态转换到另一个一致状态。保护所有定义在数据上的不变的属性(例如完整性约束),避免被置于不一致 (inconsistent)的状态。所以在事务期间,每次对数据库执行的插入、更新或删除操作,一个一致的事务将保护定义在数据上的所有完整性约束。

I(Isolation)——隔离性

在同一个环境中可能有多个事务并发执行,而每个事务都应表现为独立执行。就是说一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。也就是我们要在物理上学过的,串行。在这样串行执行处理中,串行的执行一系列事务的效果应该同于并发的执行它们。

这要求两件事:(1)在一个事务执行过程中,数据的中间的(可能不一致)状态不应该被暴露给所有的其他事务。可以理解为,事务A不能够读取事务B未提交的数据。(2)两个并发的事务应该不能操作同一项数据,避免出现脏数据。数据库管理系统通常使用锁来实现管理。

D(Durability)——持久性

简单来说,一个已提交的事务对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

事物的隔离级别(5)

Isolation 属性一共支持五种事务设置,具体介绍如下:
——DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .
——READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )
——READ_COMMITTED 会出现不可重复读、幻读问题(锁定正在读取的行)
——REPEATABLE_READ 会出幻读(锁定所读取的所有行)
——ERIALIZABLE 保证所有的情况不会发生(锁表)

事务的传播属性(7)

以前没有Spring帮助我们完成事务的时候我们必须自己手动的控制事务,如果项目中仅仅使用hibernate,我们在一个service层中调用其他的业务逻辑方法,为了保护方法之间数据是有效、一致,必须也要把当前的hibernate session传递到下一个方法中,或者采用ThreadLocal的方法,将session传递给下一个方法,现在这个工作由spring来保持事务的一致性。

在Service层的这个方法中,除了调用了Dao层的方法之外,还调用了本类的其他的Service方法,在调用其他的Service方法的时候,通过设置好的传播属性,保证我在A方法里掉用的B方法与我本身的A方法处在同一个事务中,如果遇到RuntimeException,事务才会回滚。避免方法A和方法B处理数据不一致。注意一下如果你在程序发生错误的情况下,有自己的异常处理机制定义自己的Exception,必须从RuntimeException类继承这样事务才会回滚。之后会讲一下怎么配置和管理事务。

事务的传播属性有七个:

  • PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
  • PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。
  • PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
  • PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
  • PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务
  • PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常
  • PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

我对举个例子:PROPAGATION_REQUIRED,比如 有两个方法:

    ServiceA {   
         void doSome() {   
             ServiceB.doOther();   
         }   
      }   

      ServiceB {                 
         void doOther() {   
         }          
}   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

REQUIRED——必须有事务

指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务。这种传播行为是最常见的选择,也是Spring默认的事务传播行为。

比如说,Servicedo的doOther()方法上加上了传播行为PROPAGATION_REQUIRED。若doSome()方法在调用doOther()方法时就是在事务内运行的,则doOther()方法的执行也加入到该事务内执行。若doSome()方法在调用doOther()方法时没有在事务内执行,则doOther()方法会促使doSome()创建一个事务,并在加入其中执行。在doSome()或者在doOther()内的任何地方出现异常,事务都会被回滚。即使doOther()的事务已经被提交,doSome()在接下来fail要回滚,doOther()也要回滚。

简单来说,谁调加了REQUIRED的方法,谁就要具有一个事务,被调用的方法可有可无事务,但是调他的必须有事务

这里写图片描述

猜你喜欢

转载自blog.csdn.net/f45056231p/article/details/81433256
今日推荐