JDBC中进行MySQL的事务处理操作(模拟转账操作)
简介:
进行事务操作主要是使用Connection中的方法:
开启事务:public void setAutoCommit(boolean autoCommit) throws SQLException
true:自动提交,也就是没执行一条SQL语句都是单独的事务
false:手动提交,就相当于开启事务并在提交前都处于事务的状态中
提交事务:public void commit() throws SQLException 回滚事务:public void rollback() throws SQLException
处理事务的代码格式:
try { conn.setAutoCommit(false); // 开启事务 // 执行SQL语句 // 执行SQL语句 // 执行SQL语句 // 执行SQL语句 conn.commit(); // 提交事务 }catch() { conn.rollback(); // 回滚事务 }
这样操作的话,在执行SQL语句的时候如果出现了异常,那么就马上会跳转到rollback()回滚方法,从而保证异常不会影响数据库中的数据。
同一事务中所有的操作都是一个Connection对象进行的
首先在MySQL中创建一个account表并插入几个值:
然后是Dao层的数据库连接操作代码:
package logic; import java.sql.Connection; import java.sql.SQLException; import org.junit.jupiter.api.Test; import JDBC.JdbcUtils; import dao.UpdataDao; public class TransferDemo { public void transfer(String from, String to, double money) { // 获取SQL对象 Connection conn = null; try { conn = JdbcUtils.getConnection(); // 开启事务 conn.setAutoCommit(false); // 转账 UpdataDao upd = new UpdataDao(); upd.upDate(conn, from, -money); // 减去money upd.upDate(conn, to, money); // 加上money //提交事务 conn.commit(); // 关闭资源 conn.close(); }catch(Exception e) { try { // 回滚事务 conn.rollback(); conn.close(); // 关闭资源 } catch (SQLException e1) { throw new RuntimeException(e1); } } } }
package dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; public class UpdataDao { /** * 操作数据库中的数据 * @param conn SQL对象 * @param name 要操作对象的名字 * @param money 加减的金额 */ public void upDate(Connection conn, String name, double money) { try { // SQL模板 String sql = UPDATE account SET balance=balance+? WHERE name=?; // 这个是更新数据的模板 String sqlStmt = SELECT name FROM account; // 这个检索名称的模板 // 绑定模板 PreparedStatement pstmt = conn.prepareStatement(sql); Statement stmt = conn.createStatement(); // 获取数据表 ResultSet rs = stmt.executeQuery(sqlStmt); while(rs.next()) {// 移动光标 if(rs.getString(name).equals(name)) { // 判断当前光标获取的名字是否正确 System.out.println(找到你啦!!); pstmt.setDouble(1, money); pstmt.setString(2, name); // 执行 pstmt.executeUpdate(); break; } } // 没有这个名称则抛出异常 if(rs.isAfterLast()) { // 光标已经在最后了 System.out.println(没有找到!!); throw new RuntimeException(名称不存在!!!); } stmt.close(); // stmt只在本方法中被使用,所以可以在使用后关闭 }catch (Exception e) { throw new RuntimeException(e); } } }
然后是JSP前端页面代码:
<%@taglib uri=http://java.sun.com/jsp/jstl/core prefix=c%> <!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN> <html> <head> <%@ page language=java contentType=text/html; charset=UTF-8 pageEncoding=UTF-8%> <meta http-equiv=Content-Type content=text/html; charset=UTF-8> <title>title</title> </head> <body> <div align=center> <form action=<c:url value='/AServlet'/> method=post> 转账人:<input type=text name=from/><br/><br/> 收款人:<input type=text name=to/><br/><br/> 转账金额:<input type=text name=money size=18px/><br/><br/> <input type=submit value=提交/><br/> </form> </div> </body> </html>
最后是Servlet处理请求:
package servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import logic.TransferDemo; @WebServlet(/AServlet) public class AServlet extends HttpServlet { private static final long serialVersionUID = 9081505028320745516L; private logic.TransferDemo tf = new TransferDemo(); protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(utf-8); response.setContentType(text/html;charset=utf-8); // 获取参数 String from = request.getParameter(from); String to = request.getParameter(to); double money = Double.parseDouble(request.getParameter(money)); this.tf.transfer(from, to, money); // 调用方法来设置参数 response.getWriter().print(从 + from + 转账 + money + 到 + to + 的账户上); } }
启动服务器,输入参数:
这里我分别输入了不存在的转账人、不存在的收款人和转账人、收款人 同时不存在的三种参数,查看结果:
数据库中的数据没有变化,说明进行了事务的回滚操作,那么再进行正确参数的输入:
再次查看:
这次执行后数据库进行了一加一减的数据变化,说明转账操作成功。