上一篇随笔记了一些有关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. html5--3.17 新增的表单重写

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

  2. tflearn 数据集太大无法加载进内存问题?——使用image_preloader 或者是 hdf5 dataset to deal with that issue

    tflearn 数据集太大无法加载进内存问题? Hi, all! I'm trying to train deep net on a big dataset that doesn't fit into ...

  3. Chapter2——如何分析Android程序

    前几天买了<Android软件安全与逆向分析>这本书,决定在这里记一些笔记. 第一章介绍了如何搭建环境,此处略去:第二章开始讲分析Android程序. 下面按顺序记录关键内容. ----- ...

  4. JAVA 需要理解的重点 二

    1.常用设计模式 单例模式:懒汉式.饿汉式.双重校验锁.静态加载,内部类加载.枚举类加载.保证一个类仅有一个实例,并提供一个访问它的全局访问点. 代理模式:动态代理和静态代理,什么时候使用动态代理. ...

  5. PHP多种序列化/反序列化的方法 json_encode json_decode

    序列化是将变量转换为可保存或传输的字符串的过程:反序列化就是在适当的时候把这个字符串再转化成原来的变量使用.这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性. 1. serialize和 ...

  6. 阿里云CDNapi

    #!/usr/bin/env python from aliyunsdkcore import client import json from aliyunsdkcdn.request.v201411 ...

  7. dockerfile创建镜像(二)

    ENTRYPOINT 两种格式: ENTRYPOINT [“executable”, “param1”, “param2”] ENTRYPOINT command param1 param2 (she ...

  8. 1-1 课程简介 & 2-1 IDEA与Eclipse的不同 & 2-3 Intellij IDEA安装

    ---恢复内容开始--- F:\教程\java-慕课\从网页搭建入门Java Web\Java web\步骤四:常用功能\1.IntelliJ IDEA开发工具入门 1-1 课程简介 2-1 IDEA ...

  9. sql添加表

    IF EXISTS(SELECT * FROM sysobjects WHERE name='learnRecord') DROP TABLE learnRecord GO CREATE TABLE ...

  10. 5 手写Java Stack 核心源码

    Stack是Java中常用的数据结构之一,Stack具有"后进先出(LIFO)"的性质. 只能在一端进行插入或者删除,即压栈与出栈 栈的实现比较简单,性质也简单.可以用一个数组来实 ...