JDBC事务之例子篇
上一篇随笔记了一些有关JDBC事务管理的理论知识。这篇来看例子(主要怕一篇随笔装所有东西太长了然后分开呵呵)
一般讲事务管理的,都是拿转钱来当例子的,嗯没错我们这也是。
这个是数据库中的t_account表,装的就是额~可以理解成一个银行账号,就有id,用户名,还有用户的存款。

然后是一个简单的Java实体类:
package com.java.ws.transactionDemo; /**
* 数据库的实体对应类
* 银行账号类
* @author 85060
*
*/
public class Account {
private int id;
private String accountName;
private float accountBalance; public Account(int id, String accountName, float accountBalance) {
this.id = id;
this.accountBalance = accountBalance;
this.accountName = accountName;
} public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public float getAccountBalance() {
return accountBalance;
}
public void setAccountBalance(float accountBalance) {
this.accountBalance = accountBalance;
} }
DbUtil类:是个封装了获取JDBC驱动还有连接代码的类,就不贴了,主要就是提供Connection还有关闭数据库连接和预处理。
然后来看 这个AccountInOutDao,这里我们不是很规范,逻辑代码也写在了这里:
package com.java.ws.transactionDemo; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; import com.java.ws.util.DbUtil; public class AccountInOutDao { private static DbUtil dbUtil = new DbUtil(); /* new Account(1, "张三", 500);
new Account(2, "李四", 1000);*/ public static int outMoney(Account user, int amount, Connection con) { String sql = "UPDATE t_account set accountBalance = accountBalance - ? where id = ?";
PreparedStatement pstmt = null;
int result = 0;
try { pstmt = con.prepareStatement(sql);
pstmt.setInt(1, amount);
pstmt.setInt(2, user.getId());
result = pstmt.executeUpdate();//返回执行的条数 } catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("在借钱出去的数据库操作里面出错");
e.printStackTrace();
} finally {
dbUtil.close(pstmt, con);
} return result;
} public static int inMoney(Account user, int amount, Connection con) { String sql = "UPDATE t_account set accountBalance = accountBalance + ? where id = ?";
PreparedStatement pstmt = null;
int result = 0;
try { pstmt = con.prepareStatement(sql);
pstmt.setInt(1, amount);
pstmt.setInt(2, user.getId());
result = pstmt.executeUpdate();//返回执行的条数 } catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("在借钱出去的数据库操作里面出错");
e.printStackTrace();
} finally {
dbUtil.close(pstmt, con);
} return result;
} public static void main(String[] args) {
Connection con = dbUtil.getCon();
System.out.println("张三要转钱200块了");
if(outMoney(new Account(1, "张三", 500), 200, con) != 0) {
System.out.println("成功转钱");
}
System.out.println("张三要转钱200块了");
if(inMoney(new Account(2, "李四", 1000), 200, con) != 0) {
System.out.println("成功收钱");
}
}
}
操作后结果:

这里先是一个普通且正常运行的情况,就看拿钱也成功,取钱也成功。但如果我们现在人为地在转钱和收钱中间制造一个异常的话呢?
public static void main(String[] args) {
System.out.println("张三要转钱200块了");
if(outMoney(new Account(1, "张三", 500), 200) != 0) {
System.out.println("成功转钱");
}
System.out.println(1/0); //制造了一个异常
System.out.println("张三要转钱200块了");
if(inMoney(new Account(2, "李四", 1000), 200) != 0) {
System.out.println("成功收钱");
}
}
结果就是,显而易见:


张三是转了两百块钱,然而李四啥都没收到。这要是在现实的银行系统中还得了hhh。
所以我们这里采用事务管理的方式,给个try catch块,如果抓到错误,就回滚。
public static void main(String[] args) {
Connection con = null;
try {
con = dbUtil.getCon();
con.setAutoCommit(false);
System.out.println("张三要转钱200块了");
if(outMoney(new Account(1, "张三", 500), 200, con) != 0) {
System.out.println("成功转钱");
}
System.out.println(1/0); //制造异常
System.out.println("张三要转钱200块了");
if(inMoney(new Account(2, "李四", 1000), 200, con) != 0) {
System.out.println("成功收钱");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("转账失败!");
try {
con.rollback();//有错误,回滚
System.out.println("刚刚走了回滚那一步");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {
try {
con.commit(); //最后提交,如果是没异常,则正常提交,如果有异常,就提交回滚那个位置前面的那些操作
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dbUtil.close(con);
}
}
结果:

数据库信息没变化:

刚刚我们采用全部回滚,也可以定点回滚:
Savepoint savePoint = null; savePoint = con.setSavepoint(); //记忆点 con.rollback(savePoint);//有错误,回滚到记忆点
附:
一开始我是在InMoney和OutMoney里面分别建立Connection,然后在main方法里面又搞了一个Connection用来回滚,想着说应该是可以吧,回滚到之前main这个con的初始情况。结果不行,要改成一个Connection才行。 后面百度相关信息,有看到当多个线程使用一个Connection的时候,会引起事务的混乱。。我想这也是为什么要有连接池这种技术的原因吧。
JDBC事务之例子篇的更多相关文章
- JDBC事务之理论篇
事务: 事务是数据库操作的基本逻辑单位,一般来说,事务总是并发地执行,并且这些事务可能并发地存取相同的数据.因此为了保证数据的完整性和一致性,所有的JDBC相符的驱动程序都必须支持事务管理. 事务可以 ...
- CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)
JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...
- Java事务处理全解析(八)——分布式事务入门例子(Spring+JTA+Atomikos+Hibernate+JMS)
在本系列先前的文章中,我们主要讲解了JDBC对本地事务的处理,本篇文章将讲到一个分布式事务的例子. 请通过以下方式下载github源代码: git clone https://github.com/d ...
- Java中的事务——JDBC事务和JTA事务
Java中的事务——JDBC事务和JTA事务 转载:http://www.hollischuang.com/archives/1658 之前的事务介绍基本都是数据库层面的事务,本文来介绍一下J2EE中 ...
- JTA和JDBC事务
一般情况下,J2EE应用服务器支持JDBC事务.JTA事务.容器管理事务.这里讨论JTA和JDBC事务的区别.这2个是常用的DAO模式事务界定方式.JDBC 事务 JDBC 事务是用 Connecti ...
- Java的JDBC事务详解(转)
事务的特性: 1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行. 2) 一致性(consistency):事务在完 ...
- C#.NET利用ContextBoundObject和Attribute实现AOP技术--AOP事务实现例子
我前两天看见同事用写了用AOP技术实现缓存的方案,于是好奇看了一下这是怎么实现的.原来是用了.NET中的一个类ContextBoundObject和Attribute相关技术.其实个类在.NET Fr ...
- Java的JDBC事务详解
Java的JDBC事务详解 分类: Hibernate 2010-06-02 10:04 12298人阅读 评论(9) ...
- 春天JDBC事务管理
JDBC事务管理 春天提供编程式的事务管理(编程式事务管理)与声明式的事务管理(声明式事务management),为不同的事务实现提供了一致的编程模型,这节以JDBC事务为例,介绍Spring的事务管 ...
随机推荐
- ArcGIS发布动态空间,并验证
发布 发布方法见视频. 验证 发布动态空间后,页面底部有 点进去后,使用如下语法验证. {"id": 0,"source": {"type" ...
- <ZZ>Linux rpm 命令参数使用详解[介绍和应用]
http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/10/08/2203153.html RPM是RedHat Package Manager ...
- html5--3.20 新增的keygen元素
html5--3.20 新增的keygen元素 学习要点 掌握fieldset/legend元素的用法(和figure和figcaption很像,只不过是作用于表单) 了解keygen元素的用法 fi ...
- codeforces 702A A. Maximum Increase(水题)
题目链接: A. Maximum Increase time limit per test 1 second memory limit per test 256 megabytes input sta ...
- .html 页面修改成 .jsp 后缀后中文乱码解决办法。
.html 后缀的文件,如果直接将 .html后缀改成 .jsp 后缀,则会乱码. 正确方法如下: 将如图的代码中 html 声明去掉,然后加上这段代码:<%@ page language=& ...
- call,apply,bind与es6的数组扩展运算符...
js中每一个Function对象都有一个apply个一个call方法: function.apply(thisObj,[argArray]); function.call(thisObj,arg1,a ...
- 比利牛斯獒犬 flask web
1. 使用 session.get('name') 直接从会话中读取 name 参数的值.和普通的字典一样,这里使用 get() 获取字典中键对应的值以避免未找到键的异常情况,因为对于不存在的键, g ...
- Visual Studio Ultimate 2013 下载地址
VS2013_RTM_ULT_CHS.iso 文件大小:2.87G 百度网盘下载地址: http://pan.baidu.com/s/1bn4gavX 微软官网下载地址: http://downloa ...
- 20个Flutter实例视频教程-第08节: 保持页面状态
博客地址: https://jspang.com/post/flutterDemo.html#toc-bb9 视频地址: https://www.bilibili.com/video/av397092 ...
- 常用模块 re模块与正则表达式
re模块 正则: 正则就是用一些具有特殊含义的符号组合到一起(称之为正则表达式)来描述字符或字符串的方法.或者说:正则就是用描述一类事物的规则.(在python中) 它内嵌在python中,并通过re ...