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的事务管 ...
随机推荐
- 2013 gzhu 校赛
题目描述: Integer in C++ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 128000/64000 KB (Java/Othe ...
- <编译>条件编译——判断当前使用的编译器及操作系统
有时候编译需要多平台运行的代码,需要一些条件编译,经常忘记,这里专门记录一下,方便下次查找. 编译器 GCC #ifdef __GNUC__ #if __GNUC__ >= 3 // GCC ...
- Swift Optional Chaining
Optional Chaining介绍 关于「optional chaining」,<The Swift Programming Language>是这么描述的: Optional cha ...
- [Balkan 2007] Mokia
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1176 [算法] CDQ分治 + 树状数组即可 时间复杂度 : O(Nlog^2N) ...
- java-执行dos命令
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOExce ...
- 表单提交Post方法、Get方法
表单用来接受用户的输入,并将用户的输入以“name=value值对”集合的形式提交到服务器进行处理.那么表单是怎样将数据提交到服务器的?服务器是怎样对表单数据进行处理的?下面我将为大家揭开表单提交背 ...
- Git简单教程
该笔记总结廖雪峰Git教程, 参考网站: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017 ...
- shell json简单处理
- Sudo环境变量继承
sudo中默认配置会重置环境变量,所以使用sudo的时候需要小心这点.如何让sudo继承我们需要的环境变量?有如下两种方法: #sudo visudo 或者 #vi /etc/sudoers ...
- dubbo框架介绍
1.背景 (#) 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构 当网站流量很小 ...