在進(jìn)行轉(zhuǎn)賬操作時(shí)跟衅,我們要保證數(shù)據(jù)的統(tǒng)一性。(例如璃饱,當(dāng)一個(gè)賬戶轉(zhuǎn)出金額過程中,如果出現(xiàn)系統(tǒng)錯(cuò)誤或者說是停電斷網(wǎng)等特殊情況肪康,將會(huì)發(fā)生轉(zhuǎn)出賬戶減少荚恶,轉(zhuǎn)入賬戶金額未添加的情況。)因此磷支,我們需要通過事務(wù)控制:
注意點(diǎn):在事務(wù)控制語句代碼中谒撼,要保證Connection是同一個(gè)
目錄結(jié)構(gòu):
image.png
web層servlet客戶端交互代碼:
package com.zys.transfer.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zys.transfer.service.TransferService;
public class TransferServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//接收轉(zhuǎn)賬的參數(shù),傳遞給service層
String out = request.getParameter("out");
String in = request.getParameter("in");
String moneyStr = request.getParameter("money");
double money = Double.parseDouble(moneyStr);//強(qiáng)制轉(zhuǎn)化成double類型
//調(diào)用業(yè)務(wù)層的轉(zhuǎn)賬方法
TransferService service = new TransferService();
Boolean TransferIsSuccess = service.transfer(out,in,money);
if(TransferIsSuccess){
response.getWriter().write("轉(zhuǎn)賬成功");
}else{
response.getWriter().write("轉(zhuǎn)賬失敗");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
service層業(yè)務(wù)邏輯處理代碼:
package com.zys.transfer.service;
import java.sql.Connection;
import java.sql.SQLException;
import com.zys.transfer.dao.TransferDao;
import com.zys.utils.DataSourceUtils;
public class TransferService {
public Boolean transfer(String out, String in, double money) {
TransferDao dao = new TransferDao();
Boolean TransferIsSuccess = true;
Connection conn = null;
try {
//開啟事務(wù)
conn = DataSourceUtils.getConnection();
conn.setAutoCommit(false);
//轉(zhuǎn)出錢的方法
dao.out(conn,out,money);
//轉(zhuǎn)入錢的方法
dao.in(conn,in,money);
} catch (Exception e) {
TransferIsSuccess = false;
//回滾事務(wù)
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}finally{
try {
conn.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return TransferIsSuccess;
}
}
dao層數(shù)據(jù)庫交互代碼:
package com.zys.transfer.dao;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import com.zys.utils.DataSourceUtils;
public class TransferDao {
public void out(Connection conn,String out, double money) throws SQLException {
QueryRunner runner = new QueryRunner();
//Connection conn = DataSourceUtils.getConnection();
String sql = "update account set money=money-? where name=?";
runner.update(conn, sql, money,out);
}
public void in(Connection conn,String in, double money) throws SQLException {
QueryRunner runner = new QueryRunner();
//Connection conn = DataSourceUtils.getConnection();
String sql = "update account set money=money+? where name=?";
runner.update(conn, sql, money,in);
}
}
通過TheadLocal對(duì)象獲取Connection方式實(shí)現(xiàn):
因?yàn)閟ervice層是處理業(yè)務(wù)邏輯的雾狈,dao層是處理數(shù)據(jù)庫的廓潜,conn不應(yīng)該在service層出現(xiàn),用此種方式可以實(shí)現(xiàn)善榛,而保證在一個(gè)訪問中三層架構(gòu)Connection為同一個(gè)辩蛋。
service層業(yè)務(wù)邏輯處理代碼:
package com.zys.transfer.service;
import java.sql.Connection;
import java.sql.SQLException;
import com.zys.transfer.dao.TransferDao;
import com.zys.utils.DataSourceUtils;
public class TransferService {
public Boolean transfer(String out, String in, double money) {
TransferDao dao = new TransferDao();
Boolean TransferIsSuccess = true;
Connection conn = null;
try {
//使用TheaadLocal存儲(chǔ)Connection
//開啟事務(wù)
//conn = DataSourceUtils.getConnection();
//conn.setAutoCommit(false);
DataSourceUtils.startTransaction();
//轉(zhuǎn)出錢的方法
dao.out(out,money);
//轉(zhuǎn)入錢的方法
dao.in(in,money);
} catch (Exception e) {
TransferIsSuccess = false;
//回滾事務(wù)
try {
//conn.rollback();
DataSourceUtils.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}finally{
//提交事務(wù)
try {
//conn.commit();
DataSourceUtils.commitAndRelease();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return TransferIsSuccess;
}
}
dao層數(shù)據(jù)庫交互代碼:
package com.zys.transfer.dao;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import com.zys.utils.DataSourceUtils;
public class TransferDao {
public void out(String out, double money) throws SQLException {
QueryRunner runner = new QueryRunner();
Connection conn = DataSourceUtils.getCurrentConnection();
String sql = "update account set money=money-? where name=?";
runner.update(conn, sql, money,out);
}
public void in(String in, double money) throws SQLException {
QueryRunner runner = new QueryRunner();
Connection conn = DataSourceUtils.getCurrentConnection();
String sql = "update account set money=money+? where name=?";
runner.update(conn, sql, money,in);
}
}