• 事务@Transactional注解的属性


    事务的传播行为

    当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
    事务的传播行为可以由传播属性指定。Spring定义了7种类传播行为。

    事务传播属性可以在@Transactional注解的propagation属性中定义。

    1) . 说明
      ①REQUIRED传播行为
    当bookService的purchase()方法被另一个事务方法checkout()调用时,它默认会在现有的事务内运行。这个默认的传播行为就是REQUIRED。因此在checkout()方法的开始和终止边界内只有一个事务。这个事务只在checkout()方法结束的时候被提交,结果用户一本书都买不了。
     

    ②. REQUIRES_NEW传播行为
    表示该方法必须启动一个新事务,并在自己的事务内运行。如果有事务在运行,就应该先挂起它。

    事务的隔离级别

    1、数据库事务并发问题
       假设现在有两个事务:Transaction01和Transaction02并发执行。
      1) 脏读(针对一条数据中的一个字段)
         ①Transaction01将某条记录的AGE值从20修改为30。
         ②Transaction02读取了Transaction01更新后的值:30。
         ③Transaction01回滚,AGE值恢复到了20。
         ④Transaction02读取到的30就是一个无效的值。
      2) 不可重复读(针对一条数据中的一个字段)
         ①Transaction01读取了AGE值为20。
         ②Transaction02将AGE值修改为30。
         ③Transaction01再次读取AGE值为30,和第一次读取不一致。
      3) 幻读(针对表中的一行数据而言)
         ①Transaction01读取了STUDENT表中的一部分数据。
         ②Transaction02向STUDENT表中插入了新的行。
         ③Transaction01读取了STUDENT表时,多出了一些行。
    2、 隔离级别
    数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。
      1) 读未提交:READ UNCOMMITTED
        允许Transaction01读取Transaction02未提交的修改。
      2) 读已提交:READ COMMITTED
         要求Transaction01只能读取Transaction02已提交的修改。
      3) 可重复读:REPEATABLE READ
           确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。
      4) 串行化:SERIALIZABLE
          确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。(单线程,在一个请求中,其他线程读都不可以)

    用@Transactional注解声明式地管理事务时可以在@Transactional的isolation属性中设置隔离级别。

    触发事务回滚的异常
    1、默认情况
    捕获到RuntimeException或Error时回滚,而捕获到编译时异常不回滚。
    2、设置途经
    1) 注解@Transactional 注解
     ① rollbackFor属性:指定遇到时必须进行回滚的异常类型,可以为多个
     ② noRollbackFor属性:指定遇到时不回滚的异常类型,可以为多个

     

    事务的超时和只读属性

    1、简介
     由于事务可以在行和表上获得锁,因此长事务会占用资源,并对整体性能产生影响。如果一个事务只读取数据但不做修改,数据库引擎可以对这个事务进行优化。
     超时事务属性:事务在强制回滚之前可以保持多久。这样可以防止长期运行的事务占用资源。
     只读事务属性: 表示这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务。
    2、注解设置
    @Transaction注解

    package com.atguigu.book.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Isolation;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.atguigu.book.dao.BookDao;
    import com.atguigu.book.exception.MyException;
    import com.atguigu.book.service.BookService;
    
    @Service
    //@Transactional
    public class BookServiceImpl implements BookService {
    
        @Autowired
        private BookDao dao;
        
        /**
         * @Transactional:对方法中所有的操作作为一个事务进行管理
         * 在方法上使用,只对方法有效果
         * 在类上使用,对类中所有的方法都有效果
         * @Transactional中可以设置的属性:
         * 
         * propagation:A方法和B方法都有事务,当A在调用B时,会将A中的事务传播给B方法,B方法对于事务的处理方式就是事务的传播行为
         *         Propagation.REQUIRED:必须使用调用者的事务(默认值)
         *         Propagation.REQUIRES_NEW:将调用者的事务挂起,不使用调用者的事务,使用新的事务进行处理
         * 
         * isolation:事务的隔离级别,在并发的情况下,操作数据的一种规定
         *             读未提交:脏读   1
         *             读已提交:不可重复读   2
         *             可重复读:幻读   4
         *             串行化:性能低,消耗大   8
         * 
         * 
         * timeout:在事务强制回滚前最多可以执行(等待)的时间
         * 
         * readOnly:指定当前事务中的一系列的操作是否为只读
         * 若设置为只读,不管事务中有没有写的操作,mysql都会在请求访问数据的时候,不加锁,提高性能
         * 但是如果有写操作的情况,建议一定不能设置只读
         * 
         * rollbackFor|rollbackForClassName|noRollbackFor|noRollbackForClassName:设置事务回滚的条件
         */
        
        @Transactional(propagation=Propagation.REQUIRES_NEW, timeout=3, noRollbackFor= {NullPointerException.class, MyException.class})
        public void buyBook(String bid, String uid) {
            /*try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }*/
            Integer price = dao.selectPrice(bid);
            dao.updateSt(bid);
            dao.updateBalance(uid, price);
        }
    }

     
     
  • 相关阅读:
    如何用Baas快速在腾讯云上开发小程序-系列2:搭建Phabricator开发管理平台
    如何用Baas快速在腾讯云上开发小程序-系列1:搭建API & WEB WebSocket 服务器
    腾讯云极速配置NodeJS+LNMP运行环境
    Python GTK + 3教程 学习笔记 ——(4)Widget 小部件
    Python GTK + 3教程 学习笔记 ——(3)基础
    Python GTK + 3教程 学习笔记 ——(2)入门
    Python GTK + 3教程 学习笔记——(1)安装
    打包工具pyinstaller
    pip换源
    mac brew
  • 原文地址:https://www.cnblogs.com/lemonzhang/p/12917466.html
Copyright © 2020-2023  润新知