1. 程式人生 > >JavaWeb學習筆記5——事務例項:轉賬

JavaWeb學習筆記5——事務例項:轉賬

資料庫是具有事務性的,這是資料庫與其他儲存方式的區別之一。

那麼什麼是事務性呢?簡單來說一個事務內會執行多個操作,這些操作要麼全部執行成功,要麼全部執行失敗。就比如說轉賬: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餘額不足,操作失敗,事務回滾。