問題:使用JDBC連接數據庫,實現帳號轉賬業務。從A賬戶轉賬為B賬戶500元
方案:
本案例中,要實現轉賬業務,需要執行兩次更新操作,一是更新A賬戶的金額為在原有的金額基礎上減去500元;
二是更新B賬戶的金額為在原有金額的基礎上增加500元。這兩次更新操作要麼全部成功,要麼全部失敗(事務),來表示轉賬的成功或失敗。如果A賬戶的金額更新為原來金額基礎上減去500元,而B賬戶去沒有在原有金額基礎上增加500元,這樣就造成了數據的不一致。我們可以使用事務來控制兩次更新要麼全部成功,要麼全部失敗。
本案例中,可以可以使用事務將兩次更新操作封裝成一個邏輯但願,要麼全部執行,要麼完全不執行, 保證了數據的完整性。
下列方法實現JDBC事務的基本操作;
Connection.setAutoCommit(boolean)當參數為false時,關閉自動提交
Connection.commit()提交事務
Connection.rollback()回滾事務
使用JDBC控制事務的核心代碼如下:
try { con=ConnectionSource.getConnection(); stmt=con.createStatement(); //更新數據的SQL語句 String sql1="update account set amount=amount-"+amount+"where id="+"'"+from+"'"; String sql2="update account set amount=amount+"+amount+"where id="+"'"+to+"'"; //關閉自動提交 con.setAutoCommit(false); //執行SQL語句 stmt.executeUpdate(sql1); stmt.executeUpdate(sql2); //提交 con.commit(); } catch (SQLException e) { try { con.rollback(); } catch (SQLException e1) { System.out.println("回滾事務異常!"); throw new RuntimeException(e); } System.out.println("數據庫訪問異常!"); throw new RuntimeException(e); }finally{ try { if(stmt!=null){ stmt.close(); } if(con!=null){ con.close(); } } catch (SQLException e) { System.out.println("釋放資源時發生異常!"); } }
步驟:
實現此方案需要按照如下步驟進行:
步驟一:創建Account表,並插入測試數據
在Mysql數據庫中,創建表並插入測試數據,SQL語句如下所示:
CREATE TABLE account( id CHAR(1), amount NUMERIC(10,2) ); INSERT INTO account VALUES('A',1000); INSERT INTO account VALUES('B',2000);
步驟二:准備JDBC操作數據庫的基本代碼
首先,新建類Trans,在該類中新建transfer方法,方法的聲明如下:
public void transfer(String from,String to, double amount){}
該方法表示從莊戶from轉賬給賬戶to,轉賬金額為amount。
然後,准備數據庫連接Connection對象,操作SQL語句的Statement對象並進行異常處理,代碼如下所示:
package Account; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import dao.ConnectionSource; public class Trans { public static void main(String[] args) { } public void transfer(String from,String to,double amount){ Connection con=null; Statement stmt=null; try { con=ConnectionSource.getConnection(); stmt=con.createStatement(); } catch (SQLException e) { System.out.println("數據庫訪問異常!"); throw new RuntimeException(e); }finally{ try { if(stmt!=null){ stmt.close(); } if(con!=null){ con.close(); } } catch (SQLException e) { System.out.println("釋放資源時發生異常!"); } } } }
步驟三:實現轉賬功能
使用Connection的setAutoCommit方法,commit方法以及rollback方法來控制事務,以確保轉賬功能正確實現,代碼如下所示:
package Account; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import dao.ConnectionSource; public class Trans { public static void main(String[] args) { } public void transfer(String from,String to,double amount){ Connection con=null; Statement stmt=null; try { con=ConnectionSource.getConnection(); stmt=con.createStatement(); //更新數據的SQL語句 String sql1="update account set amount=amount-"+amount+"where id="+"'"+from+"'"; String sql2="update account set amount=amount+"+amount+"where id="+"'"+to+"'"; //關閉自動提交 con.setAutoCommit(false); //執行SQL語句 stmt.executeUpdate(sql1); stmt.executeUpdate(sql2); //提交 con.commit(); } catch (SQLException e) { try { con.rollback(); } catch (SQLException e1) { System.out.println("回滾事務異常!"); throw new RuntimeException(e); } System.out.println("數據庫訪問異常!"); throw new RuntimeException(e); }finally{ try { if(stmt!=null){ stmt.close(); } if(con!=null){ con.close(); } } catch (SQLException e) { System.out.println("釋放資源時發生異常!"); } } } }
步驟四:測試
在Trans類的main方法中,笤俑transfer方法,代碼如下所示:
public static void main(String[] args) { Trans trans=new Trans(); trans.transfer("A", "B", 500); }運行Trans類,控制台無輸出,表示成功,然後查看Mysql數據庫中的account表,會發現A賬戶的金額減少了500元,B賬戶的金額增加了500元。
運行前:
運行後: