本篇将讲诉如何使用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.Driver
url=jdbc:mysql://localhost:3306/jdbcdemo
username=root
password=root

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

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

public void transaction() throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false); //开启事务,相当于start transaction命令 String sql1 = "update account set money=money-100 where name='a'";
st = conn.prepareStatement(sql1);
st.executeUpdate(); //执行SQL语句 String sql2 = "update account set money=money+100 where name='b'";
st = conn.prepareStatement(sql2);
st.executeUpdate(); //执行SQL语句 conn.commit(); //提交事务
}finally{
JdbcUtils.release(conn, st, rs);
}
}

  

查看事务执行情况:

  

通过例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.Driver
url=jdbc:mysql://localhost:3306/jdbcdemo
username=root
password=root

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

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

public void transaction() throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false); //开启事务,相当于start transaction命令 String sql1 = "update account set money=money-100 where name='a'";
st = conn.prepareStatement(sql1);
st.executeUpdate(); int x = 1/0; //在此处模拟事务处理过程中出错 String sql2 = "update account set money=money+100 where name='b'";
st = conn.prepareStatement(sql2);
st.executeUpdate(); conn.commit(); //提交事务
}finally{
JdbcUtils.release(conn, st, rs);
}
}

  

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

  

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

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

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

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

public void transaction() throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false); //开启事务,相当于start transaction命令 String sql1 = "update account set money=money-100 where name='a'";
st = conn.prepareStatement(sql1);
st.executeUpdate(); int x = 1/0; //在此处模拟事务处理过程中出错 String sql2 = "update account set money=money+100 where name='b'";
st = conn.prepareStatement(sql2);
st.executeUpdate(); conn.commit(); //提交事务
}catch (Exception e) {
e.printStackTrace();
conn.rollback(); //手动回滚该事务中所有的操作
}finally{
JdbcUtils.release(conn, st, rs);
}
}

  

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

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

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

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

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

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

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

public void transaction() throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
Savepoint sp = null; //代表回滚点对象
try{
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false); //开启事务,相当于start transaction命令 String sql1 = "update account set money=money-100 where name='a'";
st = conn.prepareStatement(sql1);
st.executeUpdate(); sp = conn.setSavepoint(); //在此处设置回滚点 int x = 1/0; //在此处模拟事务处理过程中出错 String sql2 = "update account set money=money+100 where name='b'";
st = conn.prepareStatement(sql2);
st.executeUpdate(); conn.commit(); //提交事务
}catch (Exception e) {
conn.rollback(sp); //回滚到指定的回滚点处
conn.commit(); //回滚之后再次提交事务保证回滚点之前的SQL能被执行 }finally{
JdbcUtils.release(conn, st, rs);
}
}

  

查看事务执行情况:

  

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

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

  

事务之使用JDBC进行事务的操作2的更多相关文章

  1. 事务之使用JDBC进行事务的操作

    本篇讲述数据库中非常重要的事务概念和如何使用MySQL命令行窗口来进行数据库的事务操作.下一篇会讲述如何使用JDBC进行数据库的事务操作. 事务是指数据库中的一组逻辑操作,这个操作的特点就是在该组逻辑 ...

  2. spring not_support 该方法被事务方法调用时 不会加入spring事务 只是执行jdbc普通的事务

  3. day18-事务与连接池 3.jdbc中事务操作介绍

    那么我们都是通过程序操作数据库.所以要了解jdbc下怎样对事务操作.jdbc如何操作事务? 自动事务false那就不开了呗相当于开启事务. package cn.itcast.transaction; ...

  4. Spring总结——AOP、JDBC和事务的总结

    1.上一次总结了 Spring 的核心三大组件(Core,Beans,Context),今天总结的 AOP.JDBC和事务都可以看成是核心三大组件的应用. 其中 Spring 的事务管理又以 AOP ...

  5. jdbc、事务(Transaction)、批处理 回顾

    论文写的头疼,回顾一下jdbc,换换脑子 传统的写法: 1.加载驱动类 class.forname("jdbc类的包结构"); 2.获得连接 Connection conn=Dri ...

  6. 【JDBC】事务的使用

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5868750.html 关于事务的理论知识.ACID特性等等,网上太多了,在此不一一重复.本文主要着重  事务 ...

  7. MySql事务及JDBC对事务的使用

    一 .事务的几个重要特性 1. 原子性 事务内的每个内容不可分割,是一个统一的整体.或同时进行或同时消亡. 2.一致性 事务执行前和事务执行后,状态都是统一的.如A转B 100元,A和B数据总额度没有 ...

  8. JDBC 之 事务

    1.概念:事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功. 2.数据库开启事务的命令dtl: Start transaction开启事务 Rollback回滚事务(撤销) ...

  9. JDBC之事务隔离级别以及ACID特性

    JDBC之事务隔离级别以及ACID特性 事务隔离级别: 1.更新遗失(Lost update) 两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了.这是因为系统没有 ...

随机推荐

  1. 【T-SQL进阶】02.理解SQL查询的底层原理

    本系列[T-SQL]主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]04.表表达式 ...

  2. linux下查看账号密码的过期时间和设置时间

    [root@localhost myshell]# chage -l Usage: chage [options] [LOGIN] Options: -d, --lastday LAST_DAY se ...

  3. java中的各种流(老师的有道云笔记)

    内存操作流-字节 之前的文件操作流是以文件的输入输出为主的,当输出的位置变成了内存,那么就称为内存操作流.此时得使用内存流完成内存的输入和输出操作. 如果程序运行过程中要产生一些临时文件,可采用虚拟文 ...

  4. opencv 删除二值化图像中面积较小的连通域

    对于上图的二值化图像,要去除左下角和右上角的噪点,方法:使用opencv去掉黑色面积较小的连通域. 代码 CvSeq* contour = NULL; double minarea = 100.0; ...

  5. .net 利用Emit将object转为DbParameter,DataTable转为List<>

    先放测试结果图,测试的方法是拷贝了老赵的一个简单的性能计数器:CodeTimer.发现速度还是比利用反射来获取快了2倍左右的,将object转为DbParameter的反射方法我没写.         ...

  6. 机器学习:线性判别式分析(LDA)

    1.概述      线性判别式分析(Linear Discriminant Analysis),简称为LDA.也称为Fisher线性判别(Fisher Linear Discriminant,FLD) ...

  7. Rhythmbox音乐播放器常见问题

    一.歌名中文乱码 对于所有用gstreamer做后端的播放器,如Rhythmbox, 设置如下的环境变量后即可正确读取mp3中GBK编码的id3 tag. export GST_ID3_TAG_ENC ...

  8. js替换字符串中所有指定的字符

    第一次发现JavaScript中replace() 方法如果直接用str.replace("-","!") 只会替换第一个匹配的字符.  而str.replac ...

  9. JavaScript设计模式_10_职责链模式

    职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止.职责链模式的名字非常形象,一系列可能 ...

  10. net core 程序docker打包镜像并发布到官方store

    学习一个技术的第一步,总是要先打印或显示一个hello world的.当然,学习docker也不例外.上一篇文章已经简单的介绍了环境的安装和配置.接下来就要打印我们的hello world了. 首先我 ...