在之前的学习中,我们学习了使用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. jupyter notebook新用法

    输入单词以后按下tab键以后 出现提示 a是个矩阵或者数组,a.flatten()就是把a降到一维,默认是按横的方向降>>> a = np.array([[1,2], [3,4]]) ...

  2. 2019/4/11 wen 常用类2

  3. Python3 tkinter基础 Menubutton 点击按钮出现下拉菜单

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  4. 【常见错误】Quartz常见错误

    1.集群之后把其中一个Quartz服务停了,其他的也不接手工作 问题描述 集群之后,A节点执行了大多数任务,B节点大部分时间处于空闲,停掉A节点,B节点也不会接手工作. 解决方式 修改Quartz的配 ...

  5. 论文笔记:Structure Inference Net: Object Detection Using Scene-Level Context and Instance-Level Relationships

    Structure Inference Net: Object Detection Using Scene-Level Context and Instance-Level Relationships ...

  6. MG90S 舵机 使用方法 树莓派

    来源 舵机的控制信号为周期是 20ms 的脉宽调制(PWM)信号,其中脉冲宽度从 0.5ms-2.5ms,相对应舵盘的位置为 0-180 度,呈线性变化. 也就是说,给它提供一定的脉宽,它的输出轴就会 ...

  7. 《Visual C#从入门到精通》第四章使用复合赋值和循环语句——读书笔记

    第1章 使用复合赋值和循环语句 4.1 使用复合赋值操作符 任何算术操作符都可以像这样与赋值操作符合并,从而获得复合赋值操作符. 不要这样写 要这样写 Variable=Variable*number ...

  8. Java 中断

    https://zhuanlan.zhihu.com/p/45667127 看的似懂非懂

  9. Rancher2.0导入本地RKE Kubernetes集群图解

      简要说明: 使用RKE工具在192.168.3.161机器上,创建包含两个节点的Kubernetes集群,(192.168.3.162和192.168.3.163).RKE会自动在/home/用户 ...

  10. redhat7.2安全基线BI

    (一)   Redhat linux7.2安全基线基本型(BI) 1.   密码复杂度策略 /etc/pam.d/system-auth文件中,增加内容 password requisite pam_ ...