JDBC事务之例子篇
2024-08-29 13:03:04
上一篇随笔记了一些有关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的时候,会引起事务的混乱。。我想这也是为什么要有连接池这种技术的原因吧。
最新文章
- JavaWeb基础: Cookie
- Shell命令行操作
- NumberPicker设置宽度,设置文字颜色
- 1017作业:配置java环境,学习流程图
- WCF关于svcutil生成关于绑定出现 元数据包含无法解析的引用的解决方案
- mysql 学习碎片
- 查看CPU是否支持虚拟化
- iOS开发必备HUD(透明指示层)
- 在IT网站上少花些时间
- str_replace使用array替换
- MongoDB 入门之查询(find)
- #爬虫必备,解析html文档----beautifulsoup的简单用法
- JPush极光推送 Java调用服务器端API开发
- unity3d NGUI入门(描述和使用插件参数)
- html基础知识笔记
- “乐”动人心--2017年10款最佳音乐类APP设计盘点
- shell之数组和关联数组
- springmvc复习笔记----Restful 风格,PathVariable获取 Url实例
- python3 特性
- js 判断字符串中是否包含某个字符串