垃圾版代码,只提供一个思路
第一个版本
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> <form action="${pageContext.request.contextPath}/account" method="post"> 转款人<input type="text" name="outuser"> 收款人<input type="text" name="inuser"> 金额<input type="text" name="money"> <input type="submit" value="转账"> </form> </body> </html>
servlet
public class AccountServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 1.收集数据
String outuser = request.getParameter("outuser");
String inuser = request.getParameter("inuser");
String money = request.getParameter("money");
// 2.调用AccountService中的account方法
AccountService service = new AccountService();
try {
service.account(outuser, inuser, money);
response.getWriter().write("汇款成功");
} catch (AccountException e) {
e.printStackTrace();
response.getWriter().write(e.getMessage());
}
}
}
service
public class AccountService {
// 原始转账方法
public void _account(String outuser, String inuser, String money)
throws AccountException {
AccountDao dao = new AccountDao();
// 获取连接对象,并开启事务
Connection con = null;
try {
con = JdbcUtils.getConnection();
con.setAutoCommit(false); // 开启事务
// 调用AccountDao中两个方法
// 转出
dao.accountOut(con, outuser, money);
// 转入
dao.accountIn(con, inuser, money);
} catch (SQLException e) {
e.printStackTrace();
// 事务回滚
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new AccountException("转账失败");
} catch (AccountException e) {
e.printStackTrace();
// 事务回滚
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw e;
} finally {
try {
con.commit(); // 提交事务
con.close(); // 关闭资源
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 转账方法
public void account(String outuser, String inuser, String money)
throws AccountException {
AccountDao dao = new AccountDao();
try {
// 开启事务
JdbcUtils.startTransaction();
// 转出
dao.accountOut(outuser, money);
// 转入
dao.accountIn(inuser, money);
} catch (SQLException e) {
e.printStackTrace();
// 事务回滚
try {
JdbcUtils.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new AccountException("转账失败");
} catch (AccountException e) {
e.printStackTrace();
// 事务回滚
try {
JdbcUtils.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw e;
} finally {
try {
JdbcUtils.commit();// 提交事务
JdbcUtils.closeConnection(); // 关闭资源
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
dao
public class AccountDao { // 转入 public void accountIn(Connection con, String inuser, String money) throws SQLException, AccountException { String sql = "update account set money=money+? where username=?"; PreparedStatement pst = con.prepareStatement(sql); pst.setString(1, money); pst.setString(2, inuser); int row = pst.executeUpdate(); if (row == 0) { throw new AccountException("转入失败"); } pst.close(); } // 转出 public void accountOut(Connection con, String outuser, String money) throws SQLException, AccountException { String sql = "update account set money=money-? where username=?"; PreparedStatement pst = con.prepareStatement(sql); pst.setString(1, money); pst.setString(2, outuser); int row = pst.executeUpdate(); if (row == 0) { throw new AccountException("转出失败"); } pst.close(); } // 转入--使用ThreadLocal获取连接 public void accountIn(String inuser, String money) throws SQLException, AccountException { Connection con = JdbcUtils.getConnection(); String sql = "update account set money=money+? where username=?"; PreparedStatement pst = con.prepareStatement(sql); pst.setString(1, money); pst.setString(2, inuser); int row = pst.executeUpdate(); if (row == 0) { throw new AccountException("转入失败"); } pst.close(); } // 转出 public void accountOut(String outuser, String money) throws SQLException, AccountException { Connection con = JdbcUtils.getConnection(); String sql = "update account set money=money-? where username=?"; PreparedStatement pst = con.prepareStatement(sql); pst.setString(1, money); pst.setString(2, outuser); int row = pst.executeUpdate(); if (row == 0) { throw new AccountException("转出失败"); } pst.close(); } }
exception
public class AccountException extends Exception { public AccountException() { super(); } public AccountException(String message, Throwable cause) { super(message, cause); } public AccountException(String message) { super(message); } public AccountException(Throwable cause) { super(cause); } }
//高级的,使用ThreadLocal public class JdbcUtils { private static final String DRIVERCLASSNAME; private static final String URL; private static final String USER; private static final String PASSWORD; static { ResourceBundle bundle = ResourceBundle.getBundle("jdbc"); DRIVERCLASSNAME = bundle.getString("DRIVERCLASSNAME"); URL = bundle.getString("URL"); USER = bundle.getString("USER"); PASSWORD = bundle.getString("PASSWORD"); } static { try { Class.forName(DRIVERCLASSNAME); } catch (ClassNotFoundException e) { e.printStackTrace(); } } private static final ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); // 它就相当于是一个Map集合。 public static Connection getConnection() throws SQLException { // Connection con = tl.get(); // 从ThreadLocal中获取,第一次一得到的一定是null. // if (con == null) { Connection con = DriverManager.getConnection(URL, USER, PASSWORD); // tl.set(con);// 将con装入到ThreadLocal中。 // } return con; } // 封装事务操作. // 开启事务 public static void startTransaction() throws SQLException { Connection con = getConnection(); con.setAutoCommit(false); } public static void rollback() throws SQLException { Connection con = getConnection(); con.rollback(); } // 事务提交 public static void commit() throws SQLException { Connection con = getConnection(); con.commit(); } public static void closeStatement(Statement st) throws SQLException { if (st != null) st.close(); } public static void closeResultSet(ResultSet rs) throws SQLException { if (rs != null) rs.close(); }
ThreadLocal
它的底层是使用了一个Map集合
Map<Thread,Object>
它的key就是当前的线程对象.
set(Object obj) 它就相当于 map.put(Thread.currentThread(),obj);
get()它就相当于 map.get(Thread.currentThread()));