栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

不学编程都能看懂的@Transactional()事务

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

不学编程都能看懂的@Transactional()事务

后端三郎:一名99年的宝藏开发男孩儿

看咱关系:文章对你有用的话,点赞打卡


目录

背景原因

框架版本

代码示例

表结构和数据

MjjFoodModel实体类

Controller方法

FoodService 接口

FoodServiceImpl 实现类

MjjFoodModelMapper接口

不加事务结果

使用事务结果

属性用法


背景原因

        假设我们接口修改数据,接口处理了一半,数据已经入库了,处理另一半的时候报错了,此时我们要保证已经处理完的数据回滚到未处理之前,保证数据的原子性。

        Spring的@Transactional注解可以很方便的开启事务,但是默认只在遇到运行时异常和Error时才会回滚,非运行时异常不回滚,即Exception的子类中,除了RuntimeException及其子类,其他的类默认不回滚。

框架版本

SpringBoot——2.4.1

Lombok——1.18.16

Mybatis-Plus——3.4.2

MySql——8.0.22

代码示例

表结构和数据
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for mjj_food_model
-- ----------------------------
DROP TABLE IF EXISTS `mjj_food_model`;
CREATE TABLE `mjj_food_model`  (
  `id` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键ID(uuid)',
  `food_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '美食名称',
  `food_brief` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '美食简介',
  `food_picture` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '美食图片',
  `city_id` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '城市ID',
  `city_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '城市名称',
  `create_id` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建人ID',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `update_id` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '修改人ID',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
  `is_delete` tinyint(1) NULL DEFAULT NULL COMMENT '是否删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '美食特产表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of mjj_food_model
-- ----------------------------
INSERT INTO `mjj_food_model` VALUES ('c525acf0-7763-11ec-996d-00163e0c3e0d', '牛肉丸子面', '临汾以牛肉丸子面最为有名,属于清真美食,牛肉丸子汤遍布临汾,一碗端上来,厚厚的红油看着就很有食欲,汤底是用牛骨高汤熬制,有嚼劲的丸子和劲道的面相互搭配,再加上青菜点缀,吃起来香、辣、麻,一碗下肚,很是过瘾。', '牛肉面图片', '167fa911-776e-11ec-996d-00163e0c3e0d', '临汾', '1', '2022-01-18 15:16:58', '1', '2022-01-18 15:17:05', 1);

SET FOREIGN_KEY_CHECKS = 1;

MjjFoodModel实体类
package com.example.demo.entity.food;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@AllArgsConstructor//有参构造方法
@NoArgsConstructor//无参构造方法
@Data
public class MjjFoodModel {

    
    private String id;

    
    private String foodName;

    
    private String foodBrief;

    
    private String foodPicture;

    
    private String cityId;

    
    private String cityName;

    
    private String createId;

    
    private LocalDateTime createTime;

    
    private String updateId;

    
    private LocalDateTime updateTime;

    
    private Boolean isDelete;

}

Controller方法
@RestController
@RequestMapping(value = "/food")
//swagger注解,不用可以删除
@Api(value = "后端三郎and前端小马",tags = "李淳罡VS曹长卿————美食模块")
public class FoodController {

    @Resource
    private FoodService foodService;

    @GetMapping(value = "/save")
    //swagger注解,不用可以删除
    @ApiOperation(value = "美食特产编辑",httpMethod = "GET",notes = "美食特产编辑")
    public void save(){
        foodService.save();
    }
}

FoodService 接口
    void save();

FoodServiceImpl 实现类
    
    @Resource
    private MjjFoodModelMapper mjjFoodModelMapper;

    @Override
    public void save() {
        //创建实体类
        MjjFoodModel mjjFoodModel = new MjjFoodModel();
        //复制主键ID为UUID
        mjjFoodModel.setId(UUID.randomUUID().toString());
        //美食名称
        mjjFoodModel.setFoodName("美食名称");
        //新增
        mjjFoodModelMapper.insert(mjjFoodModel);
        //写个BUG,使程序出现错误
        int a = 4/0;
    }

MjjFoodModelMapper接口
@Mapper
public interface MjjFoodModelMapper extends baseMapper {


}

不加事务结果

        启动项目,访问localhost:8081/food/save测试(端口号自己配置的)

             注:500的错误是我们故意写错的,为了看数据是否会回滚

         接口运行一半报错,此时我们查看数据发现数据却添加进去了,此时会对我们的数据造成脏数据,因为报错了你再次请求的时候就会有多条数据。不符合我们的业务逻辑。

使用事务结果

        在FoodServiceImpl 实现类的save方法上边加上@Transactional注解,再次测试

    @Override
    @Transactional
    public void save() {
        //创建实体类
        MjjFoodModel mjjFoodModel = new MjjFoodModel();
        //复制主键ID为UUID
        mjjFoodModel.setId(UUID.randomUUID().toString());
        //美食名称
        mjjFoodModel.setFoodName("美食名称");
        //新增
        mjjFoodModelMapper.insert(mjjFoodModel);
        //写个BUG,使程序出现错误
        int a = 4/0;
    }

         启动项目,访问localhost:8081/food/save测试,接口依然报错,但是我们的数据没有添加进去,遇到异常数据进行了回滚。数据还是保持原样。

属性用法

readOnly:读写或只读事务,true代表只读,false代表读写,默认读写false,例如@Transactional(readonly = true)。

rollbackFor:解决了只有运行时异常和Error才回滚的问题,用于指定回滚的异常类型。例如@Transactional(rollbackFor = Exception.class),用的Exception顶级异常,包含了所有的子类,所有的异常都可以回滚。

noRollbackFor:意思是遇到异常不进行回滚,例如@Transactional(rollbackFor = Exception.class),用的Exception顶级异常,包含了所有的子类,所有的异常都不回滚。和上一个正好相反。

propagation:事务的传播行为,默认的是REQUIRED

  REQUIRED 支持当前已经存在的事务,如果还没有事务,就创建一个新事务。  MANDATORY 支持当前已经存在的事务,如果还没有事务,就抛出一个异常。  NESTED 在当前事务中创建一个嵌套事务,如果还没有事务,那么就简单地创建一个新事务。  REQUIRES_NEW 挂起当前事务,创建一个新事务,如果还没有事务,就简单地创建一个新事务。  NEVER 强制要求不在事务中运行,如果当前存在一个事务,则抛出异常。  NOT_SUPPORTED 强制不在事务中运行,如果当前存在一个事务,则挂起该事务。  SUPPORTS 支持当前事务,如果没有事务那么就不在事务中运行。

timeout:事务的超时设置,如果超过该时间限制但事务还没有完成,则自动回滚事务。默认没有时间限制。

isolation:事务的隔离级别,使用默认的即可

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/708200.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号