JDBC中的事务回滚

news/2024/5/18 22:59:29 标签: jdbc, java, 数据库, mysql

事务回滚

  • 理解:防止出现未知错误,导致原先要执行完全的数据只执行了一半,最终影响数据,也就是 事务是一组组合成逻辑工作单元的操作,虽然系统中可能会出错,但事务将控制和维护事务中每个操作的一致性完整性

  • 事务遵循ACID原则

    1. 原子性:要么全部完成,要么都不完成
    2. 一致性:总数不变
    3. 隔离性:多个进程互不干扰
    4. 持久性:一旦提交不可逆,即持久化数据库
  • 下面在实例中体现事务回滚的作用,假设现在有个转账业务

  • 且有如下的用户信息:
    初始数据

  • 当我们想要对这个表进行如下操作:

    1. stu_id=1的用户stu_salary+1000
    2. stu_id=3的用户stu_salary-1000

正常执行的code:

java">package com.mystudy.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Affair {
    public static void main(String[] args) {
        Connection conn= null;
        PreparedStatement ps= null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1?useSSL=true","root","root");
            String sql1="UPDATE student SET stu_salary=stu_salary+1000 WHERE stu_id=1";
            ps = conn.prepareStatement(sql1);
            ps.executeUpdate();
            String sql2="UPDATE student SET stu_salary=stu_salary-1000 WHERE stu_id=3";
            ps = conn.prepareStatement(sql2);
            ps.executeUpdate();
            System.out.println("执行成功");
        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        finally {
            //资源释放
            try {
                ps.close();
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

  • 结果:

正常执行
注:很成功!

第一个执行第二个未执行的code:

  • 假设有未知原因这里将未知原因显式的定义成:int x=1/0;从而导致第一个执行,第二个尚未执行的code:
java">package com.mystudy.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Affair {
    public static void main(String[] args) {
        Connection conn= null;
        int a = 0,b=0;
        PreparedStatement ps= null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1?useSSL=true","root","root");
            String sql1="UPDATE student SET stu_salary=stu_salary+1000 WHERE stu_id=1";
            ps = conn.prepareStatement(sql1);
            ps.executeUpdate();
            int x=1/0;
            String sql2="UPDATE student SET stu_salary=stu_salary-1000 WHERE stu_id=3";
            ps = conn.prepareStatement(sql2);
            ps.executeUpdate();
            System.out.println("执行成功");
        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        finally {
            //资源释放
            try {
                ps.close();
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

  • 结果:

第一个执行,第二个没有执行
注:成功执行了第一个sql语句,但是第二个由于int x=1/0;的错误而没有执行,显然,这样是不规范的。那么就有了下面的事务回滚

  • 利用事务回滚,实现事务的原子性

两个一起执行,或者一起不执行的code:

java">package com.mystudy.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Affair {
    public static void main(String[] args) {
        Connection conn= null;
        int a = 0,b=0;
        PreparedStatement ps= null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1?useSSL=true","root","root");
            //关闭数据库的自动提交
            conn.setAutoCommit(false);
            String sql1="UPDATE student SET stu_salary=stu_salary+1000 WHERE stu_id=1";
            ps = conn.prepareStatement(sql1);
            ps.executeUpdate();
            int x=1/0;
            String sql2="UPDATE student SET stu_salary=stu_salary-1000 WHERE stu_id=3";
            ps = conn.prepareStatement(sql2);
            ps.executeUpdate();
            //业务完毕,提交事务
            conn.commit();
            System.out.println("执行成功");
        } catch (SQLException | ClassNotFoundException e) {
            try {
                //如果失败则默认回滚,
                conn.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            e.printStackTrace();
        }
        finally {
            //资源释放
            try {
                ps.close();
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

  • 结果

回滚后

  • 解释:
    1. 因为数据库自动提交的(就是执行code后读取到哪执行到哪,这也是要进行事务回滚的原因),所以我们要将数据库的自动提交关闭,那么使用codeconn.setAutoCommit(false);
    2. 关闭了自动提交,但总是要提交事务的,由该codeconn.commit();实现
    3. 上面两个设置了基本就可以实现原子性,这里为了防止意外,在catch语句中再次显式的用:conn.rollback();实现事物的回滚
  • 这里再建议学习一下sql注入问题:sql注入问题
  • 这里有JDBC简单的入门学习流程:学习流程

http://www.niftyadmin.cn/n/1674902.html

相关文章

pic单片机选型手册_PIC单片机之AD转换

AD转换我们先看看R1和R2,R2是个可调电阻如果我们将R2变大 RA0这个管脚上的电压就越大。R2变小 RA0这个管脚上的电压就越小。那单片机是怎么知道电压变化的。这就需要AD转换。就是将模拟量转换成数字量。PIC单片机如何表示电压PIC用十位二进制位的数来表示电压&#…

js生成csv文件

今天做了一个在web页面对table生成csv文件,csv可以直接用excel打开,于是就变成了,把web页面的table转成excel。 页面数据用js导出excel,在IE可以用new 一个ActiveXObject("Excel.Application" )对象来处理,但…

C#嵌入x86汇编——一个GPIO接口的实现

开始进入工业自动化,买的工控机带有GPIO接口,可用于直接控制继电器。 从厂家拿到接口手册一看,居然是汇编直接操作端口,基本上是IN/OUT指令了。接口很简单,计算位移,读取;计算位移,写…

Web过滤器

1.什么是过滤器? 2.过滤器的作用:一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤... 过滤器链(配置多个过滤器) * 执行顺序:如果有两个过滤器:过滤器1和过滤器2 1. 过滤器1 2. 过滤器2 3. 资源执…

python读取xlsx文件年月日变成数字_python转化excel数字日期为标准日期操作

伙伴遇到一个关于excel导入数据到python中,日期变成数字而不是日期格式的问题。第一反应这个数字应该是excel里面的时间戳类似的,所以我就实验增加一天是不是对应的数字就加1。最后证明了我的想法,这样就可以倒推excel里面的数字日期是从那一…

配置文件的建立与读写

以JDBC的测试连接为例学习建立和读写配置文件 学习配置文件前,先观察正常的JDBC测试连接:正常的测试连接 再看采用配置文件的方法连接: 先配置一个file文件 在该file和测试连接的Java文件下写入如下代码: file文件下&#xff1…

中文前端UI框架Kit(五)支持Css全属性/Css Hack/Css3属性/颜色渐变的Javascript动画,相比JQuery和Mooltools,功能更为强大,这不是标题党!...

中午做了几个紧急的BUG Fix,已经支持火狐,和Css Hack,请大家放心大胆的用吧 本周原本要接着KitJs的高级事件继续写下去的,不过鼠标手势还有一些技术问题需要解决,暂不放出。本周我们先来说说KitJs的Animation这个类。 …

激光打标软件_激光打标机常见问题有那些?

一、打印的笔迹含糊,打标速度过快解决办法:打标速度过快,怠慢速度。激光光斑改变,从头调校,使光斑最亮最圆,如还不可,即电话通知厂家。二、激光器的开关电源电压规范值下降,使用万用表可测得,激光电源30V电压下降,显着缺乏解决办法&#xff1…