1. 事务的概念和特性
事务一般指,一个业务逻辑包含多个DAO操作。这些DAO操作是一个整体不可分割,并且必须同时成功或同时失败。
事务具有下述4个特性
- 原子性:组成事务的这些操作是不可分割的整体
- 一致性:这些操作必须同时成功或者同时失败,不允许部分成功
- 隔离性:不同事务之间不能互相影响
- 持久性:事务执行后,结果是持久有效的
2. 基于MVC模式事务控制
MVC模式的事务控制是在Service层完成的,正常情况下Service方法中通过调用多个DAO方法来完成业务逻辑。
需要保证的事务需要的支持
-
组成事务的多个DAO方法必须使用同一个Connection对象(保证隔离性)
DAO方法中的Connection是由Service提供(传入),DAO方法执行完毕后不能关闭Connection对象。由Service层负责Connection对象的创建和回收。
DAO方法如果发生异常,必须通知Service层(保证原子性和一致性)
DAO方法中必须将异常上报,这样Service层才可以得知DAO方法的执行情况,根据DAO是否发生异常来判断Service执行是否成功
- 在Service层关闭Connection对象的自动提交功能,由程序开发者手工设置何时提交,何时回滚。(保证一致性和持久性)
Service层在执行DAO方法前,关闭自动提交,在try的结尾手工提交,在catch中手工回滚
3. 实例-转账
数据库表
DAO方法
public class SystemDAO {
public void addMoney(Connection conn, String name, double money) throws Exception {
String sql = "update accounts set money = money + ? where aname = ?";
PreparedStatement pst = null;
try {
pst = conn.prepareStatement(sql);
pst.setDouble(1, money);
pst.setString(2, name);
pst.executeUpdate();
} catch (Exception e) {
throw e;
} finally {
DBUtil.close(pst);
}
return;
}
public void descMoney(Connection conn, String name, double money) throws Exception {
String sql = "update accounts set money = money - ? where aname = ?";
PreparedStatement pst = null;
try {
pst = conn.prepareStatement(sql);
pst.setDouble(1, money);
pst.setString(2, name);
pst.executeUpdate();
} catch (Exception e) {
throw e;
} finally {
DBUtil.close(pst);
}
return;
}
}
Service方法
数据库连接工具类DBUtil略,请参照之前的例子
public class SystemService {
private SystemDAO dao = new SystemDAO();
public void zhuanzhang(String from, String to, double money) {
Connection conn = DBUtil.getConnection();
try {
conn.setAutoCommit(false); //关闭自动提交
dao.descMoney(conn, from, money);
dao.addMoney(conn, to, money);
conn.commit(); //手动提交
} catch (Exception e) {
try {
conn.rollback();//手工回滚
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {
DBUtil.close(conn);
}
}
}
Servlet
@WebServlet("/zhuanzhang")
public class ZhuanzhangServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
String m = request.getParameter("money");
double d = Double.parseDouble(m);
SystemService ss = new SystemService();
ss.zhuanzhang("赵四", "刘能", d);
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/zhuanzhang" method="post">
转账金额:<input type="text" name="money"><br>
<input type="submit" value="转账">
</form>
</body>
</html>