@Transactional事务注解的传播性

1、在常见的事务管理框架中,有以下几种事务传递的方式:

(1)REQUIRED:默认的传播行为。如果方法A在事务中被调用,并且方法A调用了方法B,则方法B将会加入到同一个事务中。如果方法A没有事务上下文,则会创建一个新的事务。

(2)REQUIRES_NEW:无论方法A是否在事务中被调用,方法B都会创建一个新的事务,并在方法B执行完毕后提交该事务。如果方法A已经存在事务,那么方法A的事务将被挂起,直到方法B的事务完成。

(3)SUPPORTS:如果方法A在事务中被调用,则方法B将加入到同一个事务中。如果方法A没有事务上下文,则方法B将以非事务方式执行。

(4)NOT_SUPPORTED:方法B将以非事务方式执行,即使方法A在事务中被调用。

(5)MANDATORY:如果方法A在事务中被调用,则方法B将加入到同一个事务中。如果方法A没有事务上下文,则会抛出异常。

(6)NEVER:如果方法A在事务中被调用,则会抛出异常。

(7)NESTED:如果方法A在事务中被调用,并且方法A调用了方法B,则方法B将在一个嵌套事务中执行。嵌套事务是外部事务的一部分,可以独立提交或回滚,但只有当外部事务成功提交时,嵌套事务才会被提交。

    这些传播行为可以根据具体的需求来选择,以实现不同的事务传递行为。需要根据具体的业务场景和需求来决定使用哪种事务传递方式。

2、以下是代码案例

(1)对应SQL

CREATE TABLE `rb_order` (
  `id` varchar(100) NOT NULL COMMENT '主键',
  `order_name` varchar(100) DEFAULT NULL COMMENT '订单名称',
  `order_price` varchar(100) DEFAULT NULL COMMENT '订单价格',
  `tr_introduce` varchar(100) DEFAULT NULL COMMENT '事物描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `rb_user` (
  `id` varchar(100) NOT NULL,
  `name` varchar(100) DEFAULT NULL,
  `password` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

(2)对应entity实体

@Data
@TableName("rb_order")
public class RbOrder {

    @TableId(type = IdType.ASSIGN_UUID)
    private String id;

    private String orderName;

    private String orderPrice;

    private String trIntroduce;
}


@Data
@TableName("rb_user")
public class RbUser {

    @TableId(type = IdType.ASSIGN_UUID)
    private String id;

    private String name;

    private Integer password;

}

(3)对应mapper文件

@Mapper
public interface RbOrderMapper extends BaseMapper<RbOrder> {
}

@Mapper
public interface RbUserMapper extends BaseMapper<RbUser> {
}

(4)对应service文件:

public interface RbOrderService extends IService<RbOrder> {
}

public interface RbUserService extends IService<RbUser> {
}

(5)对应serviceImpl文件

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RbOrderServiceImpl extends ServiceImpl<RbOrderMapper, RbOrder> implements RbOrderService {
}

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RbUserServiceImpl extends ServiceImpl<RbUserMapper, RbUser> implements RbUserService {
}

(6)对应service biz业务类

@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TransactionalBizService {

    private final RbUserService rbUserService;
    private final RbOrderService rbOrderService;


    /**
     * 事务操作 - 默认的传播行为。如果方法A在事务中被调用,并且方法A调用了方法B,则方法B将会加入到同一个事务中。如果方法A没有事务上下文,则会创建一个新的事务
     * 现象 - RbUser数据回滚,RbOrder数据回滚
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    @Transactional(rollbackFor = Exception.class)
    public void transactional1() {
        // 构建 - 事务保存对象
        RbUser transactional1 = this.convertUser("transactional1");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional1);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalRequired();

        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 事务操作 - 默认的传播行为。如果方法A在事务中被调用,并且方法A调用了方法B,则方法B将会加入到同一个事务中。如果方法A没有事务上下文,则会创建一个新的事务
     * 现象 - RbUser数据回滚,RbOrder正常创建数据
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    @Transactional(rollbackFor = Exception.class)
    public void transactional2() {
        // 构建 - 事务保存对象
        RbUser transactional2 = this.convertUser("transactional2");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional2);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        // 操作 - 事物不生效:事务方法被同一个类中的其他方法调用:默认情况下,事务是通过AOP切面来实现的。如果在同一个类中的一个方法调用另一个带有@Transactional注解的方法,事务可能不会生效。这是因为AOP切面是通过代理来实现的,代理对象无法截获同一个类内部方法的调用。为了解决这个问题,可以通过将注解添加到另一个类中的方法来实现事务传播
        // this.saveOrderTransactionalRequiredNew();
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalRequiredNew();
        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 事务操作 - 如果方法A在事务中被调用,则方法B将加入到同一个事务中。如果方法A没有事务上下文,则方法B将以非事务方式执行。
     * 现象 - RbUser数据回滚,RbOrder数据回滚
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    @Transactional(rollbackFor = Exception.class)
    public void transactional3() {
        // 构建 - 事务保存对象
        RbUser transactional3 = this.convertUser("transactional3");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional3);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalSupports();
    }

    /**
     * 事务操作 - 如果方法A在事务中被调用,则方法B将加入到同一个事务中。如果方法A没有事务上下文,则方法B将以非事务方式执行。
     * 现象 - RbUser正常创建,RbOrder正常创建
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    public void transactional3_1() {
        // 构建 - 事务保存对象
        RbUser transactional3 = this.convertUser("transactional3");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional3);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalSupports();
    }

    /**
     * 事务操作 - 方法B将以非事务方式执行,即使方法A在事务中被调用。
     * 现象 - RbUser数据回滚,RbOrder正常插入
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    @Transactional(rollbackFor = Exception.class)
    public void transactional4() {
        // 构建 - 事务保存对象
        RbUser transactional4 = this.convertUser("transactional4");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional4);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalNotSupports();
        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 事务操作 - 如果方法A在事务中被调用,则方法B将加入到同一个事务中。如果方法A没有事务上下文,则会抛出异常。
     * 现象 - RbUser数据回滚,RbOrder数据回滚
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    @Transactional(rollbackFor = Exception.class)
    public void transactional5() {
        // 构建 - 事务保存对象
        RbUser transactional5 = this.convertUser("transactional5");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional5);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalMandatory();
        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 事务操作 - 如果方法A没有事务上下文,则会抛出异常。
     * 现象 - RbUser正常创建,RbOrder数据回滚
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    public void transactional5_1() {
        // 构建 - 事务保存对象
        RbUser transactional5_1 = this.convertUser("transactional5_1");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional5_1);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalMandatory();
        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 事务操作 - 如果方法A在事务中被调用,则会抛出异常。
     * 现象 - RbUser正常创建,RbOrder数据回滚
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    @Transactional(rollbackFor = Exception.class)
    public void transactional6() {
        // 构建 - 事务保存对象
        RbUser transactional6 = this.convertUser("transactional6");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional6);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalNever();
        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 事务操作 - 如果方法A在事务中被调用,并且方法A调用了方法B,则方法B将在一个嵌套事务中执行。嵌套事务是外部事务的一部分,可以独立提交或回滚,但只有当外部事务成功提交时,嵌套事务才会被提交。
     * 现象 - RbUser正常创建,RbOrder数据回滚
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    @Transactional(rollbackFor = Exception.class)
    public void transactional7() {
        // 构建 - 事务保存对象
        RbUser transactional7 = this.convertUser("transactional7");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional7);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalNested();
        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 事务操作 - 如果方法A在事务中被调用,并且方法A调用了方法B,则方法B将在一个嵌套事务中执行。嵌套事务是外部事务的一部分,可以独立提交或回滚,但只有当外部事务成功提交时,嵌套事务才会被提交。
     * 现象 - RbUser正常创建,RbOrder数据回滚
     *
     * @return void
     * @Author 俞春旺
     * @Date 上午 11:48:14 2023年6月19日 0019
     **/
    public void transactional7_1() {
        // 构建 - 事务保存对象
        RbUser transactional7_1 = this.convertUser("transactional7_1");
        // 操作 - 保存用户数据
        boolean save = rbUserService.save(transactional7_1);
        Assert.isTrue(save, "保存失败");

        // 操作 - 新增订单数据,方法带入:@Transactional(rollbackFor = Exception.class)
        SpringUtil.getBean(TransactionalBizService.class).saveOrderTransactionalNested();
        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 转换 - 用户信息
     *
     * @param name 用户名称
     * @return com.rbgt.tr.entity.UserTest
     * @Author 俞春旺
     * @Date 下午 01:43:15 2023年6月19日 0019
     **/
    private RbUser convertUser(String name) {
        RbUser user = new RbUser();
        user.setName(name);
        user.setPassword(3306);
        return user;
    }

    /**
     * 操作 - 新增订单数据
     *
     * @param
     * @return void
     * @Author 俞春旺
     * @Date 下午 01:42:22 2023年6月19日 0019
     **/
    @Transactional(rollbackFor = Exception.class)
    public void saveOrderTransactionalRequired() {
        // 构建 - 订单数据
        RbOrder rbOrder = this.convertOrder("saveOrderTransactionalRequired", "REQUIRED");
        // 操作 - 数据逻辑
        boolean save = rbOrderService.save(rbOrder);
        Assert.isTrue(save, "新增失败");
    }

    /**
     * 操作 - 新增订单数据
     * 无论方法A是否在事务中被调用,方法B都会创建一个新的事务,并在方法B执行完毕后提交该事务。如果方法A已经存在事务,那么方法A的事务将被挂起,直到方法B的事务完成
     *
     * @param
     * @return void
     * @Author 俞春旺
     * @Date 下午 01:42:22 2023年6月19日 0019
     **/
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void saveOrderTransactionalRequiredNew() {
        // 构建 - 订单数据
        RbOrder rbOrder = this.convertOrder("saveOrderTransactionalRequiredNew", "REQUIRES_NEW");
        // 操作 - 数据逻辑
        boolean save = rbOrderService.save(rbOrder);
        Assert.isTrue(save, "新增失败");
    }

    /**
     * 操作 - 新增订单数据
     * 如果方法A在事务中被调用,则方法B将加入到同一个事务中。如果方法A没有事务上下文,则方法B将以非事务方式执行。
     *
     * @param
     * @return void
     * @Author 俞春旺
     * @Date 下午 01:42:22 2023年6月19日 0019
     **/
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void saveOrderTransactionalSupports() {
        // 构建 - 订单数据
        RbOrder rbOrder = this.convertOrder("saveOrderTransactionalSupports", "SUPPORTS");
        // 操作 - 数据逻辑
        boolean save = rbOrderService.save(rbOrder);
        Assert.isTrue(save, "新增失败");

        // 代码模拟操作失败
        Assert.isTrue(false, "数据报错");
    }

    /**
     * 操作 - 新增订单数据
     * 方法B将以非事务方式执行,即使方法A在事务中被调用。
     *
     * @param
     * @return void
     * @Author 俞春旺
     * @Date 下午 01:42:22 2023年6月19日 0019
     **/
    @Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class)
    public void saveOrderTransactionalNotSupports() {
        // 构建 - 订单数据
        RbOrder rbOrder = this.convertOrder("saveOrderTransactionalNotSupports", "NOT_SUPPORTED");
        // 操作 - 数据逻辑
        boolean save = rbOrderService.save(rbOrder);
        Assert.isTrue(save, "新增失败");
    }

    /**
     * 操作 - 新增订单数据
     * 如果方法A在事务中被调用,则方法B将加入到同一个事务中。如果方法A没有事务上下文,则会抛出异常。
     *
     * @param
     * @return void
     * @Author 俞春旺
     * @Date 下午 01:42:22 2023年6月19日 0019
     **/
    @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)
    public void saveOrderTransactionalMandatory() {
        // 构建 - 订单数据
        RbOrder rbOrder = this.convertOrder("saveOrderTransactionalMandatory", "MANDATORY");
        // 操作 - 数据逻辑
        boolean save = rbOrderService.save(rbOrder);
        Assert.isTrue(save, "新增失败");
    }

    /**
     * 操作 - 新增订单数据
     * 如果方法A在事务中被调用,并且方法A调用了方法B,则方法B将在一个嵌套事务中执行。嵌套事务是外部事务的一部分,可以独立提交或回滚,但只有当外部事务成功提交时,嵌套事务才会被提交。
     *
     * @param
     * @return void
     * @Author 俞春旺
     * @Date 下午 01:42:22 2023年6月19日 0019
     **/
    @Transactional(propagation = Propagation.NEVER, rollbackFor = Exception.class)
    public void saveOrderTransactionalNever() {
        // 构建 - 订单数据
        RbOrder rbOrder = this.convertOrder("saveOrderTransactionalNever", "NEVER");
        // 操作 - 数据逻辑
        boolean save = rbOrderService.save(rbOrder);
        Assert.isTrue(save, "新增失败");
    }

    /**
     * 操作 - 新增订单数据
     * 如果方法A在事务中被调用,则会抛出异常。
     *
     * @param
     * @return void
     * @Author 俞春旺
     * @Date 下午 01:42:22 2023年6月19日 0019
     **/
    @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
    public void saveOrderTransactionalNested() {
        // 构建 - 订单数据
        RbOrder rbOrder = this.convertOrder("saveOrderTransactionalNested", "NESTED");
        // 操作 - 数据逻辑
        boolean save = rbOrderService.save(rbOrder);
        Assert.isTrue(save, "新增失败");
    }


    /**
     * 转换 - 订单数据
     *
     * @param orderName 订单名称
     * @return com.rbgt.tr.entity.RbgtTestOrder
     * @Author 俞春旺
     * @Date 下午 01:41:00 2023年6月19日 0019
     **/
    private RbOrder convertOrder(String orderName, String trIntroduce) {
        RbOrder rbOrder = new RbOrder();
        rbOrder.setOrderName(orderName);
        rbOrder.setOrderPrice("3000");
        rbOrder.setTrIntroduce(trIntroduce);
        return rbOrder;
    }
}

(7)对应controller文件

@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TransactionalController {

    private final TransactionalBizService transactionalBizService;

    @PutMapping("/transactional1")
    public String transactional1() {
        transactionalBizService.transactional1();
        return "transactional1方法执行完成";
    }

    @PutMapping("/transactional2")
    public String transactional2() {
        transactionalBizService.transactional2();
        return "transactional2方法执行完成";
    }

    @PutMapping("/transactional3")
    public String transactional3() {
        transactionalBizService.transactional3();
        return "transactional3方法执行完成";
    }

    @PutMapping("/transactional3_1")
    public String transactional3_1() {
        transactionalBizService.transactional3_1();
        return "transactional3_1方法执行完成";
    }

    @PutMapping("/transactional4")
    public String transactional4() {
        transactionalBizService.transactional4();
        return "transactional4方法执行完成";
    }

    @PutMapping("/transactional5")
    public String transactional5() {
        transactionalBizService.transactional5();
        return "transactional5方法执行完成";
    }

    @PutMapping("/transactional5_1")
    public String transactional5_1() {
        transactionalBizService.transactional5_1();
        return "transactional5_1方法执行完成";
    }

    @PutMapping("/transactional6")
    public String transactional6() {
        transactionalBizService.transactional6();
        return "transactional6方法执行完成";
    }

    @PutMapping("/transactional7")
    public String transactional7() {
        transactionalBizService.transactional7();
        return "transactional7方法执行完成";
    }

    @PutMapping("/transactional7_1")
    public String transactional7_1() {
        transactionalBizService.transactional7_1();
        return "transactional7方法执行完成";
    }
}

(8)对应pom依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 引入父级 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>SpringBoot</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <groupId>org.springframework.boot</groupId>
    <artifactId>SpringBoot-Transactional</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--springboot程序测试依赖,如果是自动创建项目默认添加-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 包含spirng Mvc ,tomcat的包包含requestMapping restController 等注解 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- druid依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.0</version>
        </dependency>
        <!-- mybatisPlus 核心库 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

        <!-- 使用令牌桶算法实现乐观锁+限流 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.2-jre</version>
        </dependency>

        <!-- 秒杀限时 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

(9)对应yml文件

server:
  port: 10100   #  配置启动端口号

mybatis:
  config-location: classpath:mybatis.cfg.xml    #  mybatis主配置文件所在路径
  type-aliases-package: com.rbgt.tr.entity  #  定义所有操作类的别名所在包
  mapper-locations: #  所有的mapper映射文件
    - classpath:mapper/*.xml


spring: #springboot的配置
  datasource: #定义数据源
    #127.0.0.1为本机测试的ip,3306是mysql的端口号。serverTimezone是定义时区,照抄就好,mysql高版本需要定义这些东西
    #useSSL也是某些高版本mysql需要问有没有用SSL连接
    url: jdbc:mysql://127.0.0.1:3306/rbgt?serverTimezone=GMT%2B8&useSSL=FALSE
    username: root  #数据库用户名,root为管理员
    password: 123456 #该数据库用户的密码
    # 使用druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 10000
    database: 5
    password: yiautos123456

# mybatis-plus相关配置
mybatis-plus:
  # xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
  mapper-locations: classpath:mapper/*.xml
  # 以下配置均有默认值,可以不设置
  global-config:
    # 配置逻辑删除全局值(1 表示已删除,0 表示未删除)
    logic-delete-value: 1
    logic-not-delete-value: 0
    db-config:
      #主键类型 AUTO:"数据库ID自增" INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
      id-type: auto
      #字段策略 IGNORED:"忽略判断"  NOT_NULL:"非 NULL 判断")  NOT_EMPTY:"非空判断"
      field-strategy: NOT_EMPTY
      #数据库类型
      db-type: MYSQL
  configuration:
    configuration:
      # 分页插件
      # 需要配合pagehelper使用
      page-helper:
        helper-dialect: mysql
        reasonable: true
    # 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
    map-underscore-to-camel-case: true
    # 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
    call-setters-on-nulls: true
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

(10)对应项目截图

3、最后补充@Transactional失效原因

  1. 错误配置事务管理器:事务管理器负责管理事务的创建、提交和回滚。如果事务管理器配置错误或未配置,那么事务将不会生效。确保正确配置了适合的事务管理器,例如Spring中的DataSourceTransactionManager。

  2. 不是公共方法或在同一类内部调用:@Transactional注解通常应用于公共方法上,以便可以被外部调用触发事务。如果将@Transactional注解应用于非公共方法,或者在同一个类内部的方法之间相互调用,事务可能不会生效。确保@Transactional注解应用于公共方法,并通过外部调用触发事务。

  3. 异常被捕获而不是抛出:默认情况下,只有在方法中抛出未捕获的RuntimeException或Error时,事务才会回滚。如果在方法内部捕获了异常并处理了它,事务将继续提交。确保在需要事务回滚的地方适当抛出RuntimeException或Error。

  4. 事务方法被同一个类中的其他方法调用:默认情况下,事务是通过AOP切面来实现的。如果在同一个类中的一个方法调用另一个带有@Transactional注解的方法,事务可能不会生效。这是因为AOP切面是通过代理来实现的,代理对象无法截获同一个类内部方法的调用。为了解决这个问题,可以通过将注解添加到另一个类中的方法来实现事务传播。

 PS:大家少走弯路,走大道,哈哈哈

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值