Spring 中的事务处理

JDBC 中的事务处理

1、代码片段,模拟一段代码修改一份数据

    @Test
    public void test_jdbc_transaction() throws SQLException, ClassNotFoundException {
        //注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");//MySQL5以后可直接省略
        //获取数据库连接
        Connection con = null;

        try {
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/project?serverTimezone=GMT%2B8&useSSL=false","root","zcq200427");

            con.setAutoCommit(false);

            //获取执行者对象
            Statement stat = con.createStatement();
            //执行sql语句并返回结果
            String sql = "update user set name = 'cccc' where id = 1";
            int flag = stat.executeUpdate(sql);
            int i = 1 / 0;
//            //处理结果
//            while (re.next()){
//                System.out.println(re.getLong("id")+"\t"+re.getString("name")+"\t" );
//            }
        }catch (Exception e) {
//            if (con != null) {
//                con.rollback();
//            }
            e.printStackTrace();
        }
        finally {
           if (con != null) {
               con.setAutoCommit(true);
               con.close();
           }
        }
    }

1、首先由于数据库默认采用的是自动提交事务,所以需要先吧默认设置改为 FALSE
con.setAutoCommit(false);
2、手动模拟一个异常 int i = 1 / 0; 算术异常
3、捕获异常,随后进行事务回滚
4、查看数据库情况

当我们不进行数据库回滚时,我们发现这条更改的数据依然下沉到了我们的数据库当中,显然这是不正确的。
所以需要我们在捕获异常后手动进行数据库事务回滚


SpringBoot 中的事务处理

1、在启动类上添加 @EnableTransactionManagement 注解,当然不加也行因为在 spring,factoris 有默認的配置

2、在對應的 service 方法上添加 @Transactional 注解,如果在 service 類上添加注解就代表該 service
的所有 PUBLIC 类上都开启事务特性 (建议在事务方法上开启事务特性添加 @Transactional


@Transactional

Propagation propagation() default Propagation.REQUIRED; 事务默认的传播行为
Isolation isolation() default Isolation.DEFAULT; 事务默认的隔离级别


注意事项:
1、不能在非 public 方法上使用 @Transactional 否则会不生效
2、当在同一个 service 类中调用另一个事务方法时,不能直接调用,必须使用他的 bean 进行调用

    @Override
    //@Transactional(propagation = Propagation.REQUIRED , isolation = Isolation.DEFAULT , rollbackFor = Exception.class)
    @Transactional
    public Boolean updateByPrimaryKey(long id) {

        Preconditions.checkArgument(id >= 0  , "id 必须大于 0 且 不等于 0 ");
        userService.test();
        return Boolean.FALSE;
    }

    @Transactional
    public void test() {
        LambdaUpdateWrapper<User> eq =
                Wrappers.lambdaUpdate(User.class).eq( User::getId, 1)
                        .set(User::getName , "11111");
        int updateFlag = userMapper.update(null , eq);
        int i = 1 / 0;
    }

3、因为 spring 处理事务默认是使用的动态代理的方式,所以必须使用 spring 的代理类

posted @ 2023-07-13 13:29  ayiZzzz  阅读(38)  评论(0编辑  收藏  举报