上一篇随笔记了一些有关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的时候,会引起事务的混乱。。我想这也是为什么要有连接池这种技术的原因吧。

最新文章

  1. JavaWeb基础: Cookie
  2. Shell命令行操作
  3. NumberPicker设置宽度,设置文字颜色
  4. 1017作业:配置java环境,学习流程图
  5. WCF关于svcutil生成关于绑定出现 元数据包含无法解析的引用的解决方案
  6. mysql 学习碎片
  7. 查看CPU是否支持虚拟化
  8. iOS开发必备HUD(透明指示层)
  9. 在IT网站上少花些时间
  10. str_replace使用array替换
  11. MongoDB 入门之查询(find)
  12. #爬虫必备,解析html文档----beautifulsoup的简单用法
  13. JPush极光推送 Java调用服务器端API开发
  14. unity3d NGUI入门(描述和使用插件参数)
  15. html基础知识笔记
  16. “乐”动人心--2017年10款最佳音乐类APP设计盘点
  17. shell之数组和关联数组
  18. springmvc复习笔记----Restful 风格,PathVariable获取 Url实例
  19. python3 特性
  20. js 判断字符串中是否包含某个字符串

热门文章

  1. 自动化测试框架selenium+java+TestNG——TestNG详解
  2. xml文件的解析(用dom4j解析)
  3. NSMutableURLRequest,在POST方式下传递参数
  4. DB2删除表分区
  5. css中块元素和行内元素区别
  6. hdu-5000 Clone(dp)
  7. Opencv— — image offset
  8. POJ 3764 The xor-longest( 树上异或前缀和&字典树求最大异或)
  9. Linux串口通信中一种接收不到数据的问题的解决
  10. JS正则对象 RegExp(有变量的时候使用),用来匹配搜索关键字(标红)