zoukankan      html  css  js  c++  java
  • java学习笔记39(sql事物)

    在之前的学习中,我们学习了使用PreparedStatement类,使用这个类消除了sql注入的隐患,可是,还有些一些其他的隐患,这里以银行转账业务为例,

    假设  一个银行,张三在里面存了1000元,李四也在里面存了1000元,张三给李四转账500,那么张三的钱少500,李四的钱多500,可是如果转账的瞬间,张三的钱扣过后,给李四增加钱之前,假设停电了,那么钱就不见了,具体如下:

    创建一个假设银行的数据表:

    create table account
    (
      id     int auto_increment
        primary key,
      NAME   varchar(10) null,
      balnce double      null
    );

    当张三给李四转账500元时,我们用两句语句分开执行,java实现具体代码如下:

    package com.zs.Demo;
    
    import JDBCUtils.JDBCUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Scanner;
    
    public class ZhuanZhang {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入转账金额:");
            double money = sc.nextDouble();
            zhuanzhang(money);
        }
    
        private static void zhuanzhang(double money) {
            Connection conn = JDBCUtils.getConnection();
            PreparedStatement pre=null;
            try {
                //张三减少money元
                String sql = "update account set balnce = balnce-? where name=?;";
                pre = conn.prepareStatement(sql);
                pre.setDouble(1,money);
                pre.setString(2,"张三");
                pre.executeUpdate();
                //李四增加money元
                String sql2="update account set balnce = balnce+? where name=?;";
                pre = conn.prepareStatement(sql2);
                pre.setDouble(1, money);
                pre.setString(2,"李四");
                pre.executeUpdate();
                System.out.println("转账成功");
            } catch (SQLException e) {
                System.out.println("转账失败");
                e.printStackTrace();
            }finally{
                JDBCUtils.close(conn,pre);
            }
        }
    }

    运行结果:

    我们现在在张三和李四转账之间插入一个异常,假设停电,具体代码在上面代码中添加一句异常,如下:

    package com.zs.Demo;
    
    import JDBCUtils.JDBCUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Scanner;
    
    public class ZhuanZhang {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入转账金额:");
            double money = sc.nextDouble();
            zhuanzhang(money);
        }
    
        private static void zhuanzhang(double money) {
            Connection conn = JDBCUtils.getConnection();
            PreparedStatement pre=null;
            try {
                //张三减少money元
                String sql = "update account set balnce = balnce-? where name=?;";
                pre = conn.prepareStatement(sql);
                pre.setDouble(1,money);
                pre.setString(2,"张三");
                pre.executeUpdate();
                /*这里插入异常,0不能作为除数,所以这里会报错,用这种方式来假设停电之类的异常,我们会发现上
                面的语句已经执行了,到这里出现异常下面的语句不能执行,张三的钱扣了,李四的钱却没有增加,钱不见了*/
                System.out.println(100/0);
                
                //李四增加money元
                String sql2="update account set balnce = balnce+? where name=?;";
                pre = conn.prepareStatement(sql2);
                pre.setDouble(1, money);
                pre.setString(2,"李四");
                pre.executeUpdate();
                System.out.println("转账成功");
            } catch (SQLException e) {
                System.out.println("转账失败");
                e.printStackTrace();
            }finally{
                JDBCUtils.close(conn,pre);
            }
        }
    }

    运行结果:

     这时我们发现钱少了500,不见了,为了解决这种问题,数据库中,我们把这两种操作捆绑成一个事物,执行结果有两种,成功或者失败,不可以分开执行,

    执行成功称为:提交事务,出现异常或者失败称:回滚事务。

    在该例种,我们使用事物来处理时,思路如下:

      1.获取链接

      2.开启事物

      3.获取PreparedStatement对象

      4.执行两次更新操作,

      5.正常情况提交事务,出现异常时回滚事物

      6.关闭资源

    代码:

    package com.zs.Demo;
    
    import JDBCUtils.JDBCUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Scanner;
    
    /*需求分析:模拟银行转账业务,张三给李四转账,当张三的钱扣除后,李四的钱增加*/
    public class ShiWu {
        private static PreparedStatement pre;
        public static void main(String[] args) {
            Scanner sc=new Scanner(System.in);
            System.out.println("请输入转账金额:");
            double money = sc.nextDouble();
            zhuangzhang(money);
        }
    
        private static void zhuangzhang(double money) {
            //获得连接
            Connection conn=JDBCUtils.getConnection();
            try {
    //            开启事物功能
                conn.setAutoCommit(false);
    //            执行sql语句
                String sql="update account set  balnce=balnce-? where name=?";
                String sql2="update account set balnce = balnce+? where name=?";
                pre= conn.prepareStatement(sql);
                pre.setDouble(1,money);
                pre.setString(2,"张三");
                /*这里添加异常,到这里时出现异常,所以事物不成功,回滚事物,去掉下面异常语句,程序正常提交事务*/
                System.out.println(100/0);
    
                pre.executeUpdate();
                pre= conn.prepareStatement(sql2);
                pre.setDouble(1,money);
                pre.setString(2,"李四");
                pre.executeUpdate();
    //            提交事务
                conn.commit();
                System.out.println("转账成功");
            } catch (Exception e) {
                try {
    //                回滚事务
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
                System.out.println("转账失败");
            }
    //        关闭资源
            JDBCUtils.close(conn,pre);
        }
    }

    运行结果:

    正常提交的话,将代码中的异常语句注销就可以了,出现异常时,就会回滚事务,我们发现钱没有少,整个事务执行失败,异常前面的代码也没有成功执行。

  • 相关阅读:
    浅谈ES6
    iframe的应用
    vue时时监听input输入框中 输入内容 写法
    点击模态框滑动出来 抽屉
    this.$router 和this.$route 的区别
    iview框架 两侧弹框 出现第二层弹框 一闪而过的问题
    input框中的必填项之取消当前input框为必填项
    v-model 的修饰符
    单页面开发和多页面开发的优缺点
    原型继承+借用构造函数继承 的一些理解
  • 原文地址:https://www.cnblogs.com/Zs-book1/p/10643516.html
Copyright © 2011-2022 走看看