JavaWeb學習筆記5——事務例項:轉賬
阿新 • • 發佈:2018-12-08
資料庫是具有事務性的,這是資料庫與其他儲存方式的區別之一。
那麼什麼是事務性呢?簡單來說一個事務內會執行多個操作,這些操作要麼全部執行成功,要麼全部執行失敗。就比如說轉賬:A向B轉賬200元是一個事務,但他包含兩個操作,一個是A減少200元,另一個是B增加200元,這兩個操作必須都操作成功才能說這個事務執行成功,否則事務執行失敗。
事務會有兩個結果,提交(Commit)與回滾(Rollback),如果事務內的操作全部完成則提交,將結果儲存進資料庫,否則回滾,資料庫內資料不會有任何改動。
下面看一個例子
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.sql.*"%> <%@ page import="java.util.Date"%> <%@ page import="java.sql.Timestamp"%> <div style="padding: 2px; text-align: left;"> <a href="${pageContext.request.requestURI}">只顯示餘額</a> <br> <a href="${pageContext.request.requestURI}?action=a2b">A向B轉賬200元</a><br> <a href="${pageContext.request.requestURI}?action=b2a">B向A轉賬200元</a> </div> <% Connection conn=null; Statement stmt=null; ResultSet rs=null; try{ DriverManager.registerDriver(new com.mysql.jdbc.Driver());//註冊驅動 conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/account","root","root");//獲取資料庫連線 stmt=conn.createStatement(); rs=stmt.executeQuery("select * from tb_currency");//查詢結果集 %> <table bgcolor="#CCCCCC" cellspacing=1 cellpadding=5 width=100%> <caption ><FONT SIZE=4><B>轉賬記錄表</B></FONT></caption> <tr bgcolor=#DDDDDD> <th>賬號</th> <th>餘額</th> <th>最後修改日期</th> </tr> <% while(rs.next()) { String account=rs.getString("account");//獲取賬戶名 double currency=rs.getDouble("currency");//獲取賬戶餘額 String last_modifield=rs.getTimestamp("last_modified").toString();//獲取上次操作時間 out.println("<tr bgcolor=#FFFFFF>"); out.println("<td align=center>"+account+"</td>");//將賬戶名顯示在表中 out.println("<td align=center>"+currency+"</td>");//將餘額顯示在表中 out.println("<td align=center>"+last_modifield+"</td>"); //將上次操作時間顯示在表中 out.println("</tr>"); } }catch(SQLException e) { out.println("發生異常:"+e.getMessage()); e.printStackTrace(); }finally{ if(rs!=null) rs.close(); if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); } %> </table> <% String action=request.getParameter("action");//獲取action操作 if("a2b".equals(action)) { out.println("業務:A向B轉賬200元。<br/>"); try { DriverManager.registerDriver(new com.mysql.jdbc.Driver()); conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/account","root","root"); conn.setAutoCommit(false);//將自動提交設為false stmt=conn.createStatement(); String sql1="UPDATE tb_currency SET currency=currency-200 WHERE account='A'and currency>=200 "; int result1=stmt.executeUpdate(sql1); out.println("A賬號扣款200元,結果:"+ (result1==1?"成功":"失敗")+"<br/>"); String sql2="UPDATE tb_currency SET currency=currency+200 WHERE account='B'"; int result2=stmt.executeUpdate(sql2); out.println("B賬號進款200元,結果:"+ (result2==1?"成功":"失敗")+"<br/>"); if(result1==1 && result2==1) { conn.commit();//提交事務 out.println("轉賬成功,事務提交。<a href='listCurrency.jsp'>點此重新整理賬表</a>"); }else{ conn.rollback();//事務回滾 out.println("轉賬失敗,事務回滾。"); } }finally{ if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); } }else if("b2a".equals(action)) { out.println("業務:B向A轉賬200元。<br/>"); try { DriverManager.registerDriver(new com.mysql.jdbc.Driver());//註冊驅動 conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/account","root","root");//獲取連線 conn.setAutoCommit(false);//將自動提交設為false stmt=conn.createStatement(); String sql1="UPDATE tb_currency SET currency=currency-200 WHERE account='B'and currency>=200 "; int result1=stmt.executeUpdate(sql1); out.println("B賬號扣款200元,結果:"+ (result1==1?"成功":"失敗")+"<br/>"); String sql2="UPDATE tb_currency SET currency=currency+200 WHERE account='A'"; int result2=stmt.executeUpdate(sql2); out.println("A賬號進款200元,結果:"+ (result2==1?"成功":"失敗")+"<br/>"); if(result1==1 && result2==1) { conn.commit();//提交事務 out.println("轉賬成功,事務提交。 <a href='listCurrency.jsp'>點此重新整理賬表</a>"); }else{ conn.rollback();//事務回滾 out.println("轉賬失敗,事務回滾。"); } }finally{ if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); } } %>
A向B轉200,操作成功,事務提交
B向A轉200,由於B餘額不足,操作失敗,事務回滾。