Spring事务(通俗易懂)

Spring事务(通俗易懂),第1张

Spring事务(通俗易懂)

本文主要介绍Spring的实现方式、隔离级别、传播机制以及事务何时失效。

1.事务的实现方式
spring事务的实现方式有两种,编程式事务和声明式事务,编程式事务要手动管理事务,实际开发当中基本不会使用。本文主要重点介绍声明式事务,声明式事务管理有三种实现方式:基于TransactionProxyFactoryBean的方式、基于AspectJ的XML方式、基于注解的方式。下面主要介绍常用的两种
基于AspectJ的XML方式
在spring核心配置文件中添加事务管理器的配置、事务的增强以及切面

 
    
        
    

   
    
        
            
        
    

    
    
        
        
    

基于注解的方式
在spring核心配置文件中添加事务管理器的配置和开启事务注解

   
   
       
   

   
   

在事务方法中添加@Transaction注解

@Transactional
public void transferMoney(String source, String destination, Long amount) {

   transferDao.payMoney(source, amount);
   int i = 100/0;
   transferDao.collectMoney(destination, amount);
}

当然,如果是使用springboot,只需要在启动类类上添加@EnableTransactionManagement注解,开启事务支持,在事务方法中添加@Transaction注解就可以使用了。

在一个方法上面添加@Transactional注解之后,spring会基于这个类生成一个代理对象,(如果一个类当中所有的方法都没有加@Transactional注解,那么这个代理对象是不会生成的),
当使用代理对象的方法时,如果方法上存在@Transactional注解,那么代理逻辑会把事务的自动提交设置为fasle,然后再去执行原本的逻辑代码,如果执行逻辑代码没有出现异常,那么代理逻辑中就会将事务进行提交,如果执行业务逻辑方法出现了异常,那么则会将事务进行回滚。
当然,针对哪些异常回滚事务是可以配置的,可以利用@Transaction注解中的rollbackFor属性进行配置,默认情况下会对RuntimeException和Error进行回滚。
总而言之,@Transactional注解方式的事务,使用到了代理模式,代理模式参考

2.事务的隔离级别

Spring事务隔离级别比数据库事务隔离级别多一个default

    DEFAULT (默认)
    这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。

    READ_UNCOMMITTED (读未提交)
    这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。

    READ_COMMITTED (读已提交)
    保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。

    REPEATABLE_READ (可重复读)
    这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。

    SERIALIZABLE(串行化)
    这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。

3.事务的传播机制

    REQUIRED:默认的传播机制,如果当前不存在事务,则创建一个事务,如果存在事务,则加入事务SUPPORTS:如果当前不存在事务,则以非事务方式运行,如果存在,则加入MANDOTOEY:如果当前不存在事务,抛出异常,如果存在,就加入REQUIRED_NEW:如果当前不存在事务,就创建,如果存在,就挂起NOT_SUPPORTED:如果当前不存在事务,就以非事务方式运行,如果存在,就挂起当前事务NEVER:以非事务方式运行,如果当前存在事务,就抛出异常NESTED:如果当前不存在事务,就创建一个事务,如果当前存在,就在嵌套事务中执行

上面的描述想必大家都知道,那么该怎么理解呢?
举个例子:方法A 调用 方法B
上面所说的当前是描述方法A的,上面那7个属性是修饰方法B的

上面代码可以看出,方法A不存在事务,即是当前不存在事务,方法B又是默认的传播机制,所以方法A会创建一个事务,在事务当中运行。其它的以此类推。

为什么本类之间的方法调用不用this,而使用当前类对象呢?因为使用this,事务会失效,因为事务底层使用的是代理模式,this是代理模式的真实对象,testService才是代理对象。

3.spring事务什么时候会失效?

    同一个类当中的方法使用this调用会失效,因为事务是spring帮我们在底层生成了一个代理对象,如果是this的话,使用的是当前对象,而不是代理对象方法不是public,因为事务的设计就是被外部调用的,不是public就不行数据库不支持事务,如果数据库都不支持事务,那么spring再牛逼也做不了事务,像如果mysql使用的是myISIM引擎,它就不支持事务,这时候事务也会失效异常被吃掉,异常被try{} catch了,事务也是会失效的没有被spring管理

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5722069.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存