事务的应用demo2-------采用可交互的JDBC硬编码方式模拟"银行转账"

    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来进行事务管理。

转载于:https://my.oschina.net/u/1989867/blog/540912

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值