上一篇随笔记了一些有关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事务之例子篇的更多相关文章

  1. JDBC事务之理论篇

    事务: 事务是数据库操作的基本逻辑单位,一般来说,事务总是并发地执行,并且这些事务可能并发地存取相同的数据.因此为了保证数据的完整性和一致性,所有的JDBC相符的驱动程序都必须支持事务管理. 事务可以 ...

  2. CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)

    JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...

  3. Java事务处理全解析(八)——分布式事务入门例子(Spring+JTA+Atomikos+Hibernate+JMS)

    在本系列先前的文章中,我们主要讲解了JDBC对本地事务的处理,本篇文章将讲到一个分布式事务的例子. 请通过以下方式下载github源代码: git clone https://github.com/d ...

  4. Java中的事务——JDBC事务和JTA事务

    Java中的事务——JDBC事务和JTA事务 转载:http://www.hollischuang.com/archives/1658 之前的事务介绍基本都是数据库层面的事务,本文来介绍一下J2EE中 ...

  5. JTA和JDBC事务

    一般情况下,J2EE应用服务器支持JDBC事务.JTA事务.容器管理事务.这里讨论JTA和JDBC事务的区别.这2个是常用的DAO模式事务界定方式.JDBC 事务 JDBC 事务是用 Connecti ...

  6. Java的JDBC事务详解(转)

    事务的特性: 1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行. 2) 一致性(consistency):事务在完 ...

  7. C#.NET利用ContextBoundObject和Attribute实现AOP技术--AOP事务实现例子

    我前两天看见同事用写了用AOP技术实现缓存的方案,于是好奇看了一下这是怎么实现的.原来是用了.NET中的一个类ContextBoundObject和Attribute相关技术.其实个类在.NET Fr ...

  8. Java的JDBC事务详解

    Java的JDBC事务详解         分类:             Hibernate              2010-06-02 10:04     12298人阅读     评论(9) ...

  9. 春天JDBC事务管理

    JDBC事务管理 春天提供编程式的事务管理(编程式事务管理)与声明式的事务管理(声明式事务management),为不同的事务实现提供了一致的编程模型,这节以JDBC事务为例,介绍Spring的事务管 ...

随机推荐

  1. iap 应用内购买相关的解释

    应用范围app Store Review Guidelines : https://developer.apple.com/app-store/review/guidelines/  中 11.12  ...

  2. html5--3.17 新增的表单重写

    html5--3.17 新增的表单重写 学习要点 对form元素的属性做一个小结,对个别属性进行一点补充 重点掌握新增的表单重写 form元素的属性小结 action/method/enctype/n ...

  3. Mongodb GridFS——适合大小超过16MB的文件

    一.概述 GridFS是基于mongodb存储引擎是实现的“分布式文件系统”,底层基于mongodb存储机制,和其他本地文件系统相比,它具备大数据存储的多个优点.GridFS适合存储超过16MB的大型 ...

  4. js中this 的四种用法

    this 在函数执行时,this 总是指向调用该函数的对象.要判断 this 的指向,其实就是判断 this 所在的函数属于谁. 在<javaScript语言精粹>这本书中,把 this  ...

  5. 洛谷 P4660 & bzoj 1168 [ Baltic OI 2008 ] 手套 —— 分析+单调栈

    题目:https://www.luogu.org/record/show?rid=12702916 https://www.lydsy.com/JudgeOnline/problem.php?id=1 ...

  6. TX1 Gsteramer 环境配置

    安装命令: sudo add-apt-repository universe sudo add-apt-repository multiverse sudo apt-get update -tools ...

  7. 解除win10禁ping方法

    在局域网中,有一台电脑安装了win10操作系统,win10电脑连接网络没有问题,就是在其他电脑ping这台windows10电脑时就是ping不通,显示“请求超时.”.虽然这台windows10电脑联 ...

  8. mfc为对话框添加启动画面

    新建CwzdSplash类 CwzdSplash.h #pragma once class CWzdSplash : public CWnd { DECLARE_DYNAMIC(CWzdSplash) ...

  9. ElasticSearch基础+文档CRUD操作

    本篇博客是上一篇的延续,主要用来将年前学习ES的知识点做一个回顾,方便日后进行复习和汇总!因为近期项目中使用ES出现了点小问题,因此在这里做一个详细的汇总! [01]全文检索和Lucene (1)全文 ...

  10. HDU - 2181 哈密顿绕行世界问题 dfs图的遍历

    哈密顿绕行世界问题 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...