Spring事务

hi,大家好,今天为大家带来Spring事务相关介绍
在这里插入图片描述

🧊1.为什么要学事务

情景假设:疯驴子给王麻子转账100万,点击转账以后,界面突然黑屏了,那么疯驴子不知道王麻子收到钱还是没收到,所以转账和收款全部都一起成功或者一起失败,这就是事务的作用,保证了数据的完整性和一致性

🧊2.事务的定义

事务是指一系列操作或事件的集合,通常用于执行一项特定的任务或完成一项特定的工作。在计算机领域,事务通常是指一组数据库操作,这些操作要么全部执行成功,要么全部失败回滚,以保证数据的完整性和一致性。

🧊3.Spring事务的实现

Spring’事务的实现分为两种
1.Spring编程事务 2.Spring声明式任务

👀3.1Mysql事务的使用

事务在MySQL有三个操作:开启事务、提交事务、回滚事务

-- 开启事务
start transaction;
-- 业务执⾏
---
-- 提交事务
commit;
-- 回滚事务
rollback;

👀3.2Spring编程事务(手动)

@Service
public class MyService {

    @Autowired
    private MyDao myDao;
    
    @Transactional
    public void doTransactionalOperation(){
        // some code here
    }
}

@Repository
public class MyDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void saveData(String data) {
        String sql = "INSERT INTO my_table (data) VALUES (?)";
        jdbcTemplate.update(sql, data);
    }
}
 

在这个示例中,MyService类是一个Spring的@Service组件,该组件中包含了一个需要进行事务处理的方法doTransactionalOperation()。@Transactional注解指示Spring在该方法执行期间实现事务。

MyDao类是一个Spring的@Repository组件,包含了与数据库相关的操作。在saveData()方法中调用了JdbcTemplate的update()方法将数据插入到数据库中。

通过Spring的事务管理器,当MyService的doTransactionalOperation()方法被调用时,Spring将采取一系列措施,包括开启事务、执行方法、提交或回滚事务。

👀3.3Spring声明式事务(自动)

声明式事务很简单,在方法上或者类上添加@Transactional注解就可以实现
我们来用代码举个例子,

package com.example.demo.model;

import lombok.Data;

import java.time.LocalDateTime;


@Data
public class Userinfo {
    private int id;
    private String username;
    private  String password;
    private  String photo;
    private LocalDateTime createtime;
    private  LocalDateTime updatetime;
    private int state;
}

package com.example.demo.mapper;

import com.example.demo.model.Userinfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;


@Mapper
public interface UserMapper {
    @Insert("insert into userinfo(username,password) values(#{username},#{password})")

    int add(Userinfo userinfo);
}

package com.example.demo.service;

import com.example.demo.mapper.UserMapper;
import com.example.demo.model.Userinfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public int  add(Userinfo userinfo){

        return    userMapper.add(userinfo);

    }
}

package com.example.demo.controller;

import com.example.demo.model.Userinfo;
import com.example.demo.service.UserService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.pattern.PathPattern;


//测试类
    @RestController
    @RequestMapping("/user")
public class UserController {
        @Autowired
 private UserService userService;
        @RequestMapping("/add")
        @Transactional
        public  int  add(){
       Userinfo userinfo=new Userinfo();
       userinfo.setUsername("疯驴子");
       userinfo.setPassword("123");

     int result=    userService.add(userinfo);
            System.out.println("受影响的行数是"+result);
            int num=10/0;
            return 0;

        }
}

运行
在这里插入图片描述
不出意外的报错了,然后看看后台
在这里插入图片描述
数据库结果:
在这里插入图片描述
这个既完成了插入的测试,又没有插入到数据库里面,这就是@Transactional注解的强大力量:当修饰的方法或者类发生异常的时候自动回滚事务

👀3.4@Transactional注解作用范围

修饰⽅法时:只能应⽤到 public ⽅法上,否则不⽣效。
修饰类时:表明该注解对该类中所有的 public ⽅法都⽣效。

👀3.5@Transactional注解参数

参数作用
isolation设置事务的隔离级别,默认为DEFAULT。
propagation设置事务的传播行为,默认为REQUIRED
timeout设置事务的超时时间,默认为-1,表示不超时
readOnly设置事务的只读属性,默认为false
rollbackFor设置需要回滚的异常类型,可以设置多个
noRollbackFor设置不需要回滚的异常类型,可以设置多个
value作用同于别名name,用于指定事务的名称
name作用同于别名value,用于指定事务的名称

👀3.6@Transactional注意事项

@Transactional在异常被捕获的情况下不会进行事务自动回滚,因为捕获异常,动态代理就感知不到异常了,认为没有异常,自然就不会回滚
在这里插入图片描述

在这里插入图片描述
解决办法:
1.把异常继续抛出,代理对象就可以感受到异常
从而自动回滚事务
在这里插入图片描述
2.⼿动回滚事务,在⽅法中使用TransactionAspectSupport.currentTransactionStatus() 可以得到当前的事务,然后设置回滚⽅法 setRollbackOnly 就可以实现回滚

    try{
                int num=10/0;
            }catch (Exception e){
                    //throw e;
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }

👀3.7@Transactional工作原理

@Transactional 是基于 AOP 实现的,AOP ⼜是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理,如果目标对象没有实现了接口,会使用CGLIB动态代理

@Transactional 在开始执行业务之前,通过代理先开启事务,在执行成功之后再提交事务。如果中途遇到异常,则回滚事务

如果该注解被应用于类级别,则该类中的所有方法都将受到该注解的影响,即所有方法都将在同一个事务中执行。

总之,@Transctional注解的工作原理是通过在方法执行前创建事务,并在方法执行后根据执行结果提交或回滚事务来确保数据的一致性。但需要注意的是,该注解只能用于Spring管理的Bean对象中,否则无效。
在这里插入图片描述

🧊4.事务隔离级别

👀4.1事务特性回顾

事务有四大特性:原子性,持久性,一致性,隔离性

原子性(Atomicity)一组操作作为一个整体,要么全部执行成功,要么全部失败回滚。
一致性(Consistency):事务执行前后,数据必须保持一致状态。即,如果事务执行成功,则数据状态必须符合约束条件,否则事务将回滚。
隔离性(Isolation):事务的执行必须与其他事务隔离,以防止并发事务的相互影响。通常有四种隔离级别:读未提交、读已提交、可重复读和串行化。
持久性(Durability):一旦事务执行成功,它对数据库的影响应该是永久性的,即使系统崩溃也不应该丢失数据。

只有隔离性(隔离级别)是可以设置的,为了保证多个并发事务的执行安全,确保数据库的数据完整性、一致性和并发性.

👀4.2Mysql事务隔离级别

MySQL事务隔离级别有4种

1.READ UNCOMMITTED:读未提交

最低级别,允许一个事务读取另一个事务还未提交的数据。

2. READ COMMITTED:读已提交

允许一个事务读取另一个已经提交的事务的数据。

3. REPEATABLE READ:可重复读

可重复读,是 MySQL 的默认事务隔离级别,它能确保同⼀事务多次查询的结果⼀致

4.SERIALIZABLE:序列化

最高级别,所有事务串行执行,保证数据的完整性和一致性,但并发性能较差。

🐶!!!重点来了
1.什么是幻读?
2.RR解决幻读问题了吗?
3.咋样解决的?

什么是幻读

幻读是指在并发访问数据库时,一个事务多次查询同一数据集合时,其他事务插入或删除了数据,导致该事务前后两次查询结果不一致的现象
幻读不是重复读的现象,是查询到了不同的数据

RR解决幻读问题了吗

RR解决了部分幻读问题

咋样解决的?

🤔采用RR+MVCC(多版本并发控制)来解决幻读问题
幻读分为当前读和快照读

当前读:MVCC解决不了,进行当前读时,可能会读取到正在被修改的数据,这样可能会导致读取到不一致的数据.

解决办法:采用锁来解决,当前事务执行完释放锁,其余的事务再执行

快照读:MVCC可以解决,MVCC会为每个事务创建一个版本号,所有对数据的修改都会创建新的版本号。可以在读取数据时返回之前的版本,这个版本是在读取之前提交的,以保证数据的一致性.

🐷彻底解决幻读:
1.使用串行化隔离级别
2.RR+加锁,RR级别下加锁,开启事务就加锁,其他事务在操作此表的相关数据时,就只能等待锁释放(事务一提交或回滚锁自动释放)

当前读:数据库中一种读取数据的方式,它读取最新提交的数据
快照读:快照读是指在读取数据时,读取的是在事务开始前提交的快照数据,而不是当前的数据。如果数据在事务中发生了更新操作,快照读会读取到旧的数据,这会导致数据不一致性问题。

👀4.3Spring设置事务隔离级别

在这里插入图片描述

👀4.4Spring事务隔离级别

Spring 事务隔离级别有 5 种

Isolation.DEFAULT(默认):以连接的数据库的事务隔离级别为主
Isolation.READ_UNCOMMITTED(读未提交):最低的隔离级别,事务可以看到其他未提交的事务所做的修改
Isolation.READ_COMMITTED(读已提交):读取已提交的数据,一个事务只能看到其他事务已经提交的数据;

Isolation.REPEATABLE_READ(可重复读):同一个事务中多次读取同一个数据总是相同,不会受其他事务的影响;
Isolation.SERIALIZABLE(串行化):最高的隔离级别,所有事务都像串行执行一样,避免任何并发问题。

今天的讲解就到这里 ,我们下期再见了,886~在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值