1. 数据表-----BANKACCOUNT
create table BANKACCOUNT
(
id VARCHAR2(255) not null,
name VARCHAR2(255) not null,
balance NUMBER(10)
)
tablespace TS_USER
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 64K
next 1M
minextents 1
maxextents unlimited
);
alter table BANKACCOUNT
add primary key (ID)
using index
tablespace TS_USER
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
next 1M
minextents 1
maxextents unlimited
);
2. 初始数据
3. Test2.java------------------利用事务模拟简单的"转帐"情景
package com.lxh.transaction2;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.JOptionPane;
import com.util.ConnectToDB;
public class Test3 {
public Connection conn = null;
public Statement stat = null;
public ResultSet rs = null;
public static void main(String[] args) {
JOptionPane.showMessageDialog(null, "转帐开始:请输入对方帐号名和转帐金额");
String name = JOptionPane.showInputDialog("请输入对方帐户名:");
String money = JOptionPane.showInputDialog("请输入转帐金额:");
if (null == name || "".equals(name) || null == money
|| "".equals(money)) {
JOptionPane.showMessageDialog(null, "帐号和转帐金额不能为空");
} else {
// 判断转帐金额是否为数字
char m[] = money.toCharArray();
boolean flag = true;
for (char c : m) {
if (!(Character.isDigit(c))) {
flag = false;
break;
}
}
if (flag) {
int tradeMoney = Integer.parseInt(money);
/**
* 校验帐户名和转帐金额
*/
Test3 t = new Test3();
try {
/**
* 数据库连接操做
*/
Class.forName("oracle.jdbc.driver.OracleDriver");
t.conn = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521:tran",
"test", "123");
t.stat = t.conn.createStatement();
/********************** 转帐前置处理 **********************/
boolean userExist = Test3.checkAccount(t.stat, name);
// 用户存在
if (userExist) {
// 转帐帐户正常
boolean tradeMoneyIsAvail = Test3.checkTradeMoney(
t.stat, "lxh", tradeMoney);// 模拟lxh为转出帐户
if (tradeMoneyIsAvail) {
// 转帐金额正常
/********************** 转帐开始 ***************************/
String sql1 = "update bankAccount set balance=balance-"
+ tradeMoney + " where name='lxh'";
String sql2 = "update bankAccount set balance=balance+"
+ tradeMoney + " where name='" + name + "'";
/**
* 设置非自动提交-------很是重要
*/
t.conn.setAutoCommit(false);
// 批处理
t.stat.addBatch(sql1);
t.stat.addBatch(sql2);
/**
* 处理执行SQL的结果
*/
int res[] = t.stat.executeBatch();
int result = 1;// 正常执行,返回结果为1
for (int i : res) {
result = i;
}
if (1 == result) {
JOptionPane.showMessageDialog(
null,
"转帐成功,您的当前帐户余额为("
+ Test3.getBalance(t.stat,
"lxh") + ")");
// 执行结果所有为1的时候执行正确,容许提交
t.conn.commit();
t.conn.setAutoCommit(true);
} else {
// 不符合逻辑(SQL执行出错),回滚事务
JOptionPane.showMessageDialog(null,
"转帐失败。。。请核查输入参数");
t.conn.rollback();
}
/********************** 转帐结束 ***************************/
} else {
JOptionPane.showMessageDialog(
null,
"尊敬的lxh用户,您的帐户余额为("
+ Test3.getBalance(t.stat, "lxh")
+ ")小于转帐金额" + tradeMoney
+ ",不能转帐。");
}
} else {
JOptionPane.showMessageDialog(null, "帐户: " + name
+ " 不存在,请输入正确的帐户名.");
}
/********************** 转帐前置处理 **********************/
} catch (SQLException e) {
System.out.println("转帐失败:\t" + e.getMessage());
try {
// 出现异常回滚(好比数据表名称/字段名称有误,参数有误)
t.conn.rollback();
t.conn.setAutoCommit(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
} finally {
// 关闭资源
ConnectToDB.closeResultSet(t.rs);
ConnectToDB.closeStatemet(t.stat);
ConnectToDB.closeConnection(t.conn);
}
} else {
// 非数字直接结束
JOptionPane.showMessageDialog(null, "转帐金额应该为数字.");
}
}
}
/***************************** 工具方法 *******************************/
// 校验帐户名
public static boolean checkAccount(Statement stat, String userName) {
//
boolean flag = true;
//
int result = 0;
//
try {
ResultSet rs = stat
.executeQuery("select count(1) res from bankAccount where name='"
+ userName + "'");
while (rs.next()) {
result = rs.getInt("res");
}
// 账户名不存在
if (result != 1) {
flag = false;
}
} catch (SQLException e) {
System.out.println("" + e.getMessage());
}
//
return flag;
}
// 校验转帐金额
public static boolean checkTradeMoney(Statement stat, String userName,
int tradeMoneyValue) {
// flag
boolean flag = false;
//
int balance = 0;
// 获取帐户金额并判断转帐金额是否能够转帐
balance = getBalance(stat, userName);
if (tradeMoneyValue <= balance) {
flag = true;
}
//
return flag;
}
// 查询余额
public static int getBalance(Statement stat, String userName) {
//
int result = 0;
//
try {
//
ResultSet rs = stat
.executeQuery("select balance from bankAccount where name='"
+ userName + "'");
while (rs.next()) {
result = rs.getInt("balance");
}
} catch (SQLException e) {
System.out.println("获取帐户余额失败:\t" + e.getMessage());
}
//
return result;
}
}
4. 运行结果
<1> 帐户名不存在
<2> 金额错误
<3> 余额不足
<4> 转帐信息(帐户:xiaowu 金额:500)正确

5. 结果分析 其实跟"事务的应用demo1-------采用JDBC硬编码方式实现银行转帐."没有本质区别,只是多了与用户交互的操做,以及相关数据的验证和相关信息的显示。 6. 不足之处:转帐方是固定的。 固然这只是为了说明事务的做用作的simple demo,离真正的银行转帐逻辑以及实现还有很大差异。 7. 补充: 实际开发中,可能会使用spring来进行事务管理。