java中的事务(一)

参考转载:https://blog.csdn.net/yehuang_0801/article/details/75246413

事务定义深究:https://blog.csdn.net/amghost/article/details/17651891

事务:数据库应用中完成单一逻辑功能的操作集合,是一个既具有原子性又具有一致性的功能,我们要求事务不违反任何数据库的一致性约束,也就是说,如果事务启动时数据是一致的,那么当这个事务成功结束的时候数据库也应该是一致的

  • 事务有四大特征

1.原子(原子性:事务的所有操作在数据库中要么全部正确反映,要么全部不反映。

try{
      doA()//单独的一次数据库操作
      doB()
      doC()
      ...
}catch(AnyException){
    unDoA(),unDoB(),unDoC()

}

2.一致

一致就涉及到事务了,定义为事务结束后,所有的人拿到的数据、索引都应该是一致的。

个人理解:就是原子操作完之后,所有的人拿到的数据、索引都应该是一致的。

3.隔离

保证不同的事务相互独立、透明地执行。
级联废弃:如果事务T1读到了事务T2未提交(没有commit,虽然操作数据库成功)的数据,如果T2提
交失败,那么T1也要回滚。

  • 隔离级别:
Read Uncommitted(读未提交)
Read Committed(读已提交)
Repeatable Read(可重复读)(MySQL默认隔离级别)
Serializable(串行化)

  • 脏读、不可重复读、幻读:
脏读:一事务对数据进行了增删改,但未提交,有可能回滚,另一事务却读取了未提交的数据。

不可重复读: 一事务对数据进行了更新或删除操作,另一事务两次查询的数据不一致。 

幻读: 一事务对数据进行了新增操作,另一事务两次查询的数据不一致。

脏读:主要是针对列内容的变化。

幻读:主要是针对行数的变化。


  • Spring事务管理 @Transacational

1、Isolation(隔离性):
DEFAULT:  使用数据库设置
READ_UNCOMMITTED: 会出现脏读、不可重复读、幻读 
READ_COMMITTED: 会出现不可重复读、幻读问题
REPEATABLE_READ: 会出幻读
SERIALIZABLE: 保证所有的情况不会发生

2、propagation (传播性):

  • 1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
  • 2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
  • 3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
  • 4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
  • 5、PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • 6、PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
  • 7、PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

事务回滚理解案例:https://blog.csdn.net/hsgao_water/article/details/52860380羡慕

注意:spring通过扫描所有含有注解的@Trasation的方法,使用aop形成事务增强advise。但是加入增强时是通过代理对象调用方法的形式加入的,如果将doB()方法放在doA()方法同样的类对象直接调用时,在调用doB()方法的时候是通过当前对象来调用doB()方法的,而不是通过代理来调用的doB()方法,这个时候doB()方法上加的事务注解就失效了不起作用。惊恐

3、代码分析

[java]  view plain  copy
  1. public class TxTest{  
  2.   
  3.    @Transacational  
  4.    public void foo(){  
  5.        bar();  
  6.    }  
  7.   
  8.    @Transacational(propagation=”required_new”)  
  9.    public void bar(){  
  10.   
  11.    }  
  12. }  

调用foo()方法只会创建当前方法的事务,方法里面bar()即使定义required_new也不会创建新的事务。

[java]  view plain  copy
  1. public class TxTest{  
  2.     @Autowird  
  3.     private TxTest2 txTest2;  
  4.    @Transacational  
  5.    public void foo(){  
  6.        txTest2.bar();  
  7.    }  
  8. }  
  9.   
  10. public class TxTest2{  
  11.  @Transacational(propagation=”required_new”)  
  12.     public void bar(){  
  13.   }  
  14. }  
调用foo()方法会创建当前方法的事务,运行到txTest2.bar()时会创建一个新的事务。


猜你喜欢

转载自blog.csdn.net/qq_34638435/article/details/80688367