使用JDBC进行数据库的事务操作(2)

  本篇将讲诉如何使用JDBC进行数据库有关事务的操作。在上一篇博客中已经介绍了事务的概念,和在MySQL命令行窗口进行开启事务,提交事务以及回滚事务的操作。

  似乎事务和批处理都可以一次同时执行多条SQL命令,但是事务是如果某一条SQL出错,则前面已经执行过的SQL全部都将回滚;而批处理中某一条SQL出错,那么这条出错的SQL要么会抛出个异常,要么以一个代表出错的值返回,已经执行过的SQL不受影响,至于后面的SQL是否还会执行则看数据库,不同数据库有不同的处理。

  在前一篇我们说过,数据库对于事务是默认自动提交的,也就是发一条SQL命令则数据库就执行一条。而对于JDBC而言,当向数据库获取一个链接Connection对象,在默认情况下通过Connection对象发送的SQL命令也是默认自动提交事务的。

操作:

  ① 如果我们想使用JDBC对多条SQL进行整体执行,需要先提交事务命令,这一步是通过Connection对象先将自动提交关闭,调用Connection对象的setAutoCommit(false)方法即可。这个方法相当于在MySQL命令行窗口中输入”start transaction”命令。

  ② 如果我们在JDBC已经将自动提交关闭的情况下需要提交事务,则调用Connection对象的commit()方法即可。

  ③ 如果我们在JDBC已经将自动提交关闭的情况下需要回滚事务,则调用Connection对象的rollback(…)方法即可。rollback方法如果是无参,则回滚前面所有已执行的SQL命令;如果是有参,则可以指定回滚点,保留前面部分指定的已执行的SQL命令。

  下面以几个案例来像上一篇博客一样分别介绍几种事务的相关操作。

例1:正确提交事务的小案例

  在这个简单的案例中,通过用户A向用户B转账100元来快速了解如何使用JDBC操作事务。

创建数据库和表,另外再添加两条数据:

    create database jdbcdemo;use jdbcdemo;create table account(id int primary key auto_increment,name varchar(40),money double);insert into account(name,money) values('a',1000);insert into account(name,money) values('b',1000);

先看看准备的数据:

  

创建工程,在工程中导入数据库连接驱动的jar包。在【src】目录下新建一个database.properties文件,内容如下:

    driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/jdbcdemousername=rootpassword=root

构建JDBC的工具类,包括注册驱动,获取连接,释放资源和连接等,这部分同《JDBC操作数据库的学习(2)》中相同,此处略。

使用JDBC完成事务操作的demo代码如下:

 1 public void transaction() throws SQLException {
 2         Connection conn = null;
 3         PreparedStatement st = null;
 4         ResultSet rs = null;
 5         try{
 6             conn = JdbcUtils.getConnection();
 7             conn.setAutoCommit(false);  //开启事务,相当于start transaction命令
 8             
 9             String sql1 = "update account set money=money-100 where name='a'";
10             st = conn.prepareStatement(sql1);
11             st.executeUpdate();     //执行SQL语句
12             
13             String sql2 = "update account set money=money+100 where name='b'";
14             st = conn.prepareStatement(sql2);
15             st.executeUpdate();    //执行SQL语句
16             
17             conn.commit();   //提交事务
18         }finally{
19             JdbcUtils.release(conn, st, rs);
20         }
21     }
View Code

查看事务执行情况:

  

通过例1中简单的代码就完成了事务的一系列操作。可以看到用户A向用户B确实转账了100元。

例2:事务执行过程出错回滚的小案例

  通过前一篇博客,我们知道如果在事务执行过程中发生了错误,则数据库将会使该事务中所有的操作都回滚,那么我们在使用JDBC的情况下也来重新模拟一次,依然还是用户A向用户B转账100元。

  将例1中的account表所有用户的金额重新制定为1000元的SQL命令:

    update account set money=1000;

  

创建工程,在工程中导入数据库连接驱动的jar包。在【src】目录下新建一个database.properties文件,内容如下:

    driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/jdbcdemousername=rootpassword=root

构建JDBC的工具类,包括注册驱动,获取连接,释放资源和连接等,这部分同《JDBC操作数据库的学习(2)》中相同,此处略。

在使用JDBC进行事务处理中,我们添加一个显而易见的错误:int x = 1/0 ,如下代码:

 1 public void transaction() throws SQLException {
 2         Connection conn = null;
 3         PreparedStatement st = null;
 4         ResultSet rs = null;
 5         try{
 6             conn = JdbcUtils.getConnection();
 7             conn.setAutoCommit(false);  //开启事务,相当于start transaction命令
 8             
 9             String sql1 = "update account set money=money-100 where name='a'";
10             st = conn.prepareStatement(sql1);
11             st.executeUpdate();
12             
13             int x = 1/0;      //在此处模拟事务处理过程中出错
14             
15             String sql2 = "update account set money=money+100 where name='b'";
16             st = conn.prepareStatement(sql2);
17             st.executeUpdate();
18             
19             conn.commit();   //提交事务
20         }finally{
21             JdbcUtils.release(conn, st, rs);
22         }
23     }
View Code

  当我们执行这个Java方法时,由于设置了int x = 1/0这个逻辑错误,程序会抛出异常,但是因为抛出异常后,后面的代码不再执行,也就是说程序无法执行到提交事务conn.commit()方法处,因此数据库将会回滚该事务所有的操作,因此A与B的金额还是原来那样:

  

例3:事务执行过程出错由开发者手动回滚的小案例

  在例2中当事务执行过程中出错时,会由数据库自动回滚所有的操作,而在JDBC中,我们也可以调用链接Connection对象的rollback()方法回滚所有的操作,在下面的案例中,我们将在捕获异常的代码块中手动回滚所有的操作。

  所有表、表中数据、配置文件和JDBC工具类都同例2相同。

  将例2中的代码修改为如下:

 1 public void transaction() throws SQLException {
 2         Connection conn = null;
 3         PreparedStatement st = null;
 4         ResultSet rs = null;
 5         try{
 6             conn = JdbcUtils.getConnection();
 7             conn.setAutoCommit(false);  //开启事务,相当于start transaction命令
 8             
 9             String sql1 = "update account set money=money-100 where name='a'";
10             st = conn.prepareStatement(sql1);
11             st.executeUpdate();
12             
13             int x = 1/0;      //在此处模拟事务处理过程中出错
14             
15             String sql2 = "update account set money=money+100 where name='b'";
16             st = conn.prepareStatement(sql2);
17             st.executeUpdate();
18             
19             conn.commit();   //提交事务
20         }catch (Exception e) {
21             e.printStackTrace();
22             conn.rollback();    //手动回滚该事务中所有的操作
23         }finally{
24             JdbcUtils.release(conn, st, rs);
25         }
26     }
View Code

  效果和例2也是一样的,事务出错则回滚所有的操作。

例4:指定事务回滚点的案例

  例3的手动回滚其实有些鸡肋,与其说是手动回滚,其实即使没有调用rollback该事务就不会执行成功,而rollback方法更高级的功能在于能回滚到指定的地方。

  通过链接Connection对象的setSavepoint()方法即可在该方法所在的位置设置回滚点对象,当调用rollback(回滚点对象)方法即可将事务回滚到这个位置。这样在执行回滚之后,再次调用提交事务(Commit),则回滚点之前的SQL还是执行的。

  以例2为前提,我们在会发生异常地方的前面设置回滚点,而使第一条SQL语句能被执行,即用户A的操作能执行(减少100),用户B的操作不能执行(金额不变)。

  所有表、表中数据、配置文件和JDBC工具类都同例2相同。

将例2中的代码修改为如下:

 1 public void transaction() throws SQLException {
 2         Connection conn = null;
 3         PreparedStatement st = null;
 4         ResultSet rs = null;
 5         Savepoint sp = null;   //代表回滚点对象
 6         try{
 7             conn = JdbcUtils.getConnection();
 8             conn.setAutoCommit(false);  //开启事务,相当于start transaction命令
 9             
10             String sql1 = "update account set money=money-100 where name='a'";
11             st = conn.prepareStatement(sql1);
12             st.executeUpdate();
13             
14             sp = conn.setSavepoint();   //在此处设置回滚点
15             
16             int x = 1/0;      //在此处模拟事务处理过程中出错
17             
18             String sql2 = "update account set money=money+100 where name='b'";
19             st = conn.prepareStatement(sql2);
20             st.executeUpdate();
21             
22             conn.commit();   //提交事务
23         }catch (Exception e) {
24             conn.rollback(sp);    //回滚到指定的回滚点处
25             conn.commit();        //回滚之后再次提交事务保证回滚点之前的SQL能被执行
26             
27         }finally{
28             JdbcUtils.release(conn, st, rs);
29         }
30     }
View Code

查看事务执行情况:

  

  可以看到结果正如我们希望的那样,由于用户A的操作在回滚点之前,又因为执行回滚之后还执行了提交事务,因此回滚点之前的SQL命令还是可以被执行成功的。因此切记,要想使用回滚点,一定要在回滚之后再次提交事务,否则设置回滚点是没有意义的。

  下图是一张上面例子的执行流程:

  

 

 

 

              

 

转载于:https://www.cnblogs.com/fjdingsd/p/5272986.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谷歌浏览器之如何快速找到js、css等文件

1 问题 我们分析前端代码的时候,需要快速定位某个js文件,然后查看里面的源代码 2 具体操作 比如我在www.baidu.com这个页面,我们先按下F12, 然后点击到network,然后我们再用快捷键 ctrl p 比如我们要找tu_d03f361.js 效果如下&#x…

ASP.NET Session的七点认识(转)

ASP.NET Session的使用当中我们会遇到很多的问题,那么这里我们来谈下经常出现的一些常用ASP.NET Session的理解: ASP.NET Session的七点认识之一对于值类型的变量,Session中保存的是值类型的拷贝 Session["__test0"] 1; inti (int)…

php 读取三级分类,php excel 导入 导入三级分类 表格应该怎么设计才能得到想要的数据格式?汗血宝马...

array (size16)0 >array (size7)0 > float 11 > string 销售部 (length9)2 > string 销售1区 (length10)3 > string 销售1科室 (length13)4 > null5 > null6 > null1 >array (size7)0 > float 21 > null2 > null3 > string 销售2科室 (…

ABP会臃肿吗?

有了ABP,还要学其他的框架?我有时候在想在JAVA领域,Spring基本一统天下,新手也好,高手也罢都在学习、研究和项目实战。也就是说其实对与应用开发,Spring已经是绕不开的框架,不管是单体还是微服务…

python如何正则匹配浮点值_Python正则表达式字符串数组到浮点数组

我是python正则表达式的初学者.我达到了我所需要的,但是由于缺少经验,这真的很丑.我的目标是转换以下形式的字符串数组:notes ["10.0% higher", "5.0% lower", "Same as", "21.2% lower"]到一个float数组,这样上面的数组将…

php stripslashes 去除反斜线

stripslashes可以去除反斜线&#xff0c;准确的说是去掉一个反斜线&#xff0c;因为如果是两个反斜线的话stripslashes会把两个反斜线替换成一个&#xff1a; 引用php手册的例子&#xff1a; <?php $str "Is your name O\reilly?";// 输出: Is your name Ore…

HTML5 播放器

随着 HTML5 的普及&#xff0c;越来越多视频网站使用 <video></video> 标签播放直播、点播内容&#xff08;如下图所示&#xff09;。使用 <video> 的好处&#xff0c;主要以下两点。 可以直接在页面中播放&#xff0c;也就是所谓的“区域播放”&#xff0c;…

linux shell之控制台打印各种颜色字体和背景

1 问题 控制台打印各种颜色字体和背景 字体颜色 #30:黑 #31:红 #32:绿 #33:黄 #34:蓝色 #35:紫色 #36:深绿 #37:白色 背景颜色 #40:黑 #41:深红 #42:绿 #43:黄色 #44:蓝色 #45:紫色 #46:深绿 #47:白色 echo -e "\e[43;35m chenyu\e[0m hello word&quo…

修改GIT的user.name和user.email

为什么80%的码农都做不了架构师&#xff1f;>>> $ git config --global --replace-all user.email "输入你的邮箱" $ git config --global --replace-all user.name "输入你的用户名" ----验证是否修改成功---- $ git config --list 转载…

python包实际怎么使用_Python--模块与包

模块1、什么是模块&#xff1f;一个模块就是一个Python文件&#xff0c;文件名就是模块名字加上.py后缀。因此模块名称也必须符合变量名的命名规范。1 使用python编写的代码(.py文件)2 已被编译为共享库或DLL的C或C扩展3 包好一组模块的包4 使用C编写并链接到python解释器的内置…

php获取虚拟机ip,php如何获取用户的ip地址

直接上代码/*** 获取客户端IP地址*/function real_ip(){$ip $_SERVER[REMOTE_ADDR];if (isset($_SERVER[HTTP_X_FORWARDED_FOR]) && preg_match_all(#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s,$_SERVER[HTTP_X_FORWARDED_FOR], $matches)) {foreach ($matches[0] AS $xi…

sql distinct 去重复 (mysql)

DISTINCT 去重复 &#xff08;运动扭伤腰。。。悲伤。。。 (▼ _ ▼) &#xff09; 首先&#xff0c;例如我们的表&#xff1a; 首先观察表&#xff1a; 其中第二行和第三行和第八行的name1的只是重复的&#xff0c;但第八行的age1确是12&#xff0c;与第二行和第三行不同…

如何5分钟上手使用OCR

随便打开一个Microsoft Visual Studio&#xff0c;新建一个WinForms项目&#xff0c;从下面列表中随便选择一个NET框架。net35;net40;net45;net451;net452;net46;net461;net462;net47;net471;net472;net48; netstandard2.0;netcoreapp3.1; net5.0;net6.0;创建完窗口后&#xff…

GDI与OpenGL与DirectX之间的区别

图形编程的几种技术对比&#xff1a; GDI&#xff0c;图形设备接口&#xff0c;MS开发的通用的windows系统图形编程接口&#xff0c;功能强涉及面广&#xff0c;一般的编程都用它。但是用来做多媒体开发就差强人意了 OPENGL是SGI开发的一套三维图形软件包&#xff0c;出现很早&…

HDU 5238 Calculator 线段树 中国剩余定理

题意&#xff1a; 给一个计算器&#xff0c;有一系列计算步骤&#xff0c;只有加&#xff0c;乘&#xff0c;幂三种运算。 有一种查询操作&#xff1a;查询初始值为\(x\)的时候&#xff0c;最终运算结果模\(29393\)的值。 有一种修改操作&#xff1a;可以修改第\(p\)个运算的运…

linux shell之把文本里面的;替换成\n格式输出

1 问题 一个文本里面很多中间很多&#xff1b;然后&#xff0c;现在需要把&#xff1b;替换成\n,然后换行打印出来 比如文件1.txt namechenyu;sexman;age27 我们可以用tr命题替换&#xff0c;第一个参数是需要替换的内容&#xff0c;第二个参数是将要替换的内容 2 实现 ca…

利用Excel VBA批量计算气象数据多个台站多年来春季和冬季降水量和平均气温

气象数据是地理数据的重要组成部分,存储量虽然不大,但是处理过程非常繁琐,长时序数据更不用说。本文总结了一个气象数据的基本处理方法。 如下图所示,气象数据的排列格式是区站号→年→月→降水量→平均气温,时间范围为1983~2012年,每一年都有台站数300多个,下面按区站…

VMware Workstation 12新建虚拟机

1、点击“创建新的虚拟机”2、选择“自定义”(初学选择典型也可以)&#xff0c;下一步3、默认&#xff0c;直接下一步4、通常都是先创建虚拟机&#xff0c;等虚拟机创建完成后再来安装操作系统&#xff0c;若安装过程出现什么问题方便解决&#xff0c;故选择“稍后安装操作系统…

sql count用法_SQL学习笔记3:count(*)函数

1.count(*)函数用法COUNT(*) 函数返回表中的记录数&#xff0c;具体来说&#xff0c;返回值是一个数字。语法&#xff1a;返回表中所有记录的数量&#xff1a;SELECT COUNT(*) FROM table_name返回表中满足一定条件的记录的数量&#xff1a;SELECT COUNT(*) FROM table_name WH…

sql order by,desc和limit使用(mysql)

(&#xff61;ŏ_ŏ) 首先我们来看一个表&#xff1a; 在此我们要进行排序&#xff0c;按降序排序&#xff0c;就是从大到小。然后我们只要查询前2条数据。 意思就是我们需要把这个表从大到小排序后&#xff0c;取前两条&#xff0c;那么我们就需要使用到order by 和desc …