在之前的学习中,我们学习了使用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);
}
}

运行结果:

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

java学习笔记39(sql事物)的更多相关文章

  1. 【初学Java学习笔记】SQL语句调优

    1, 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2,应尽量避免在 where 子句中对字段进行 null 值判断,创建表时NULL是默认 ...

  2. Java学习笔记39(转换流)

    转换流:字符流和字节流之间的桥梁 用于处理程序的编码问题 OutputStreamWriter类:字符转字节流 写文本文件: package demo; import java.io.FileOutp ...

  3. 【转】JAVA学习笔记----PL/SQL最差实践

    1. 超长的PL/SQL代码   影响:可维护性,性能   症状:    在复杂的企业应用中,存在动辄成百上千行的存储过程或上万行的包.为什么是最差:    太长的PL/SQL代码不利于阅读,第三方工 ...

  4. Java学习笔记4

    Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...

  5. Oracle学习笔记三 SQL命令

    SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)  

  6. Java学习笔记(04)

    Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...

  7. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  8. 20145330第九周《Java学习笔记》

    20145330第九周<Java学习笔记> 第十六章 整合数据库 JDBC入门 数据库本身是个独立运行的应用程序 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 JD ...

  9. Java学习笔记心得——初识Java

    初识Java 拿到这本厚厚的<Java学习笔记>,翻开目录:Java平台概论.从JDK到TDE.认识对象.封装.继承与多态...看着这些似懂非懂的术语名词,心里怀着些好奇与担忧,就这样我开 ...

随机推荐

  1. 【python】python嵌套循环内层循环只执行一次

    今天写了一个两个基因集找相同的基因然后输出这么个小程序就无论如何也跑不起来,原因出在循环嵌套上,这方面之前就出过问题,后来阴差阳错的就好了我也没太注意,但是最近这个问题严重制约了工作效率,我决心找到问 ...

  2. java 43 接口

  3. Docker Kubernetes 服务发现原理详解

    Docker Kubernetes  服务发现原理详解 服务发现支持Service环境变量和DNS两种模式: 一.环境变量 (默认) 当一个Pod运行到Node,kubelet会为每个容器添加一组环境 ...

  4. shell爬虫--抓取某在线文档所有页面

    在线教程一般像流水线一样,页面有上一页下一页的按钮,因此,可以利用shell写一个爬虫读取下一页链接地址,配合wget将教程所有内容抓取. 以postgresql中文网为例.下面是实例代码 #!/bi ...

  5. UVA1329 Corporative Network

    思路 用带权并查集维护到根的距离即可 代码 #include <cstdio> #include <algorithm> #include <cstring> #i ...

  6. [ajax] - 上传图片,视频后的路径回传及确定逻辑

    业务场景1: 后台要上传视频,图片到网站的首页或者附页,上传后,视频,图片存储到服务器或cdn,但是此时还要加确定按钮以实现该视频,图片路径数据库的插入操作. 页面展现: 点击操作按钮,触发input ...

  7. visio连接线设置

    以下画图是在新建空白模式的 默认的连线,如下图, 通过设置设计模式,可以把直角线编程直的线段, 设置如下图, 效果,如下图, 如果想在上面的图的线加箭头,可以一条一条加,但是,但是效率太低,我们可以通 ...

  8. P1122 最大子树和

    传送门 思路: 任意找一个点为树根.DFS 遍历树,如果子树和为负就直接跳过,不然就统计进答案.( 虽是任意取一点为根,但不一定从这个点出发能够取得最优解,要开一个 ans 记录一下最大值.) 标程: ...

  9. 【Core内存】.NET Core 2.0中使用MemoryCache

    说到内存缓存大家可能立马想到了HttpRuntime.Cache,它位于System.Web命名空间下,但是在ASP.NET Core中System.Web已经不复存在.今儿个就简单的聊聊如何在ASP ...

  10. MVC _Ajax的使用【七】

    一.本篇主要写的是在MVC项目中一种ajax的使用方法 1.  首先在控制器中创建两个方法,showCreate()和AddUserInfo() using System; using System. ...