事务

一、什么时候需要开启事务?

当发生多条sql 增删改时才需要开启

二、事务的四大特性

一致性
​ A 给 b 转 100 ,执行连个sql A 减100,B加100 ,总金额不发生变化
隔离性
两个sql session之间 ,一个sql session能否看到另一个 sql session 增删改的数据
就是允许 一个sql session能否看到(读取到)另一个 sql session 增删改 但是还未提交的数据 (脏数据)
​ 隔离级别:允许脏数据的程度
原子性
​ 原子不可分割,多条sql语句(一般是多条增删改) 执行,要么都成功,要么豆失败(如果有一条失败,其他成功的回滚)
持久性
​ 掉电不丢失,持久到磁盘中

开启事务,关闭自动提交  sqlSessionFactory.openSession(false);
关闭事务,开启自动提交  sqlSessionFactory.openSession(true);
 /**
     * 测试事务
     *
     *      开启事务,关闭自动提交  sqlSessionFactory.openSession(false);
     *      关闭事务,开启自动提交  sqlSessionFactory.openSession(true);
     *
     */
    @Test
    public void updateRoleTest(){


        try {
            Role role = new Role();
            role.setId(1);
            role.setRolename("班长3");

            int num =  roleDao.updateRole(role);

            if (num>0){
                System.out.println("更新成功");
            }

            int i =  1/0;

            Role role2 = new Role();
            role2.setId(2);
            role2.setRolename("组长3");

            int num2 =  roleDao.updateRole(role2);

            if (num2>0){
                System.out.println("更新成功");
            }


            // 开启事务 不会自动提交,需要手动提交
            sqlSession.commit();
        } catch (Exception e){
            e.printStackTrace();

            System.out.println("事务回滚");
            // 发生异常时 回滚
            sqlSession.rollback();
        }
    }

三、Propagation 传播行为

【重点】:
传播行为:就是事务在方法间传播的策略
REQUIRED: 如果调用方法(method1) 已经开启了事务,那么再调用method2 时,method2 就不用开始事务使用method1 开启的事务.如果method1没有开启事务 method2 自己开启事务
SUPPORTS:如果调用方法(method1) 已经开启了事务,method2就是使用method1的事务,如果method1没有开启事务,method2 也不开启事务
REQUIRES_NEW:如果调用方法(method1) 已经开启了事务,method2就是不使用method1的事务,自己在开启一个新的事务.如果method1没有开启事务,method2 也开启事务

REQUIRED:指定当前方法必需在事务环境中运行,如果当前有事务环境就加入当前正在执行的事务环境,如果当前没有事务,就新建一个事务。这是默认值。即有事务就在事务中执行,没有就新建一个事务
SUPPORTS:指定当前方法加入当前事务环境,如果当前没有事务,就以非事务方式执行。即有无事务无所谓。
MANDATORY:指定当前方法必须加入当前事务环境,如果当前没有事务,就抛出异常。 即没有事务绝对不行。
REQUIRES_NEW:指定当前方法总是会为自己发起一个新的事务,如果发现当前方法已运行在一个事务中,则原有事务被挂起,我自己创建一个属于自己的事务,直我自己这个方法commit结束,原先的事务才会恢复执行。 即有事务也得新建一个事务。
NOT_SUPPORTED:指定当前方法以非事务方式执行操作,如果当前存在事务,就把当前事务挂起,等我以非事务的状态运行完,再继续原来的事务。 即必须以非事务运行。
NEVER:指定当前方法绝对不能在事务范围内执行,如果方法在某个事务范围内执行,容器就抛异常,只有没关联到事务,才正常执行。 即绝对不能再事务中运行。
NESTED:指定当前方法执行时,如果已经有一个事务存在,则运行在这个嵌套的事务中.如果当前环境没有运行的事务,就新建一个事务,并与父事务相互独立,这个事务拥有多个可以回滚的保证点。就是指我自己内部事务回滚不会对外部事务造成影响,只对DataSourceTransactionManager事务管理器起效。 即内部事务独立执行。

在这里插入图片描述

四、Isolation 隔离级别

隔离级别:就是两个事务之间,一个事务能够看到另一个事务 提交数据(未提交)的程度

允许脏数据的程度:

脏读:一个事务可以读取另一个没有提交的事务
不可重复读(不一致):一个事务查询同一行数据两次,结果允许不一样
幻读:一个事务查询执行同一sql( select * from student_tb where sex=F) 查询两次 两次数量不一致

隔离级别:

读未提交: 允许脏读 允许 重复读 允许幻读
读已提交:不允许脏读 允许 不可重复读 允许幻读
可重复读:不允许脏读 不允许不可重复读 允许幻读
序列化读:不允许脏读 不允许 不可重复读 不允许幻读

在这里插入图片描述

 // 开启事务
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED
    ,timeout = 2000) // 为当前方法 开启事务
    @Override
    public int deleteStudentByIds(List<Integer> ids) {

        // 当前方法执行多条sql
        // 事务 如果 一条增删改sql 失败都失败 其他成功的 回滚
        for (Integer id : ids) {
           int num =  studentDao.deleteStudentById(id);
           int i = 1/0;
           if (num==0){
               return 0;
           }
        }

        return 1;
    }

五、读写性

readonly 读写性

  • true:只读,可提高查询效率。(适合查询)
  • false:可读可写。 (默认值)(适合增删改)

六、事务超时

timeout事务超时时间
当前事务所需操作的数据被其他事务占用,则等待。

  • 100:自定义等待时间100(秒)。
  • -1:由数据库指定等待时间,默认值。(建议)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值