事務的應用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來進行事務管理。
相關文章
相關標籤/搜索