JDBC事务:
cmd 命令上的事务开启: start transaction; / begin;
回滚 rollback;
提交 commit;
JDBC事务控制:
开启事务:conn.setAutoCommit(false);
提交:conn.commit();
回滚:conn.rollback();
DBUtils的事务控制 也是通过jdbc
ThreadLocal:实现的是通过线程绑定的方式传递参数
事务回滚后 ,一定要commit 才能算这个事务完成
jdbc事务的运用
form 提交表单
<fieldset> <legend> 转账</legend> <form action="${pageContext.request.contextPath}/transferServlet" method="post"> 转出账户:<input type="text" name="outName"><br/><br> 转入账户:<input type="text" name="inName"><br><br> 转账金额 :<input type="text" name="money"><br/><br> <input type="submit" value="确定"> </form> </fieldset>
web 层 servlet doGet 和doPost 方法:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); String inName=request.getParameter("inName"); String outName=request.getParameter("outName"); String moneystr=request.getParameter("money"); double money=Double.parseDouble(moneystr); //调用service层的方法 TransferService transfer=new TransferService(); boolean falg = transfer.transfermoney(inName,outName,money); if (falg) { response.getWriter().write("转账成功"); }else { response.getWriter().write("转账失败"); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }
service 层类:
package com.study.transfer.service; import java.sql.Connection; import java.sql.SQLException; import com.study.transfer.dao.TransferDao; import com.study.util.C3P0Utils; public class TransferService { public boolean transfermoney(String inName, String outName, double money) { //调用dao层的inMoney 和 outMoney TransferDao dao=new TransferDao(); Connection conn=null; //dao 层 的conn //jdbc事务的处理 conn SQL语句的执行 和事务的提交,回滚需要时同一个conn; boolean isTransfer=true; int number1=-1; int number2=-1; try { //缺点是 出现了dao层的conn连接 , conn=C3P0Utils.getConnection(); conn.setAutoCommit(false); number1=dao.inMoney(conn,inName ,money); // int a=1/0; number2=dao.outMoney(conn,outName,money); if (number1==-1 || number2==-1) { //当sql语句的任何一条没有执行成功,就回滚的初始状态 conn.rollback(); } } catch (Exception e) { isTransfer=false; try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally{ try { conn.commit(); //把事务提交,结束,最后把conn返回给连接池 } catch (SQLException e) { e.printStackTrace(); } } return isTransfer; } }
dao层:
1 package com.study.transfer.dao; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 6 import org.apache.commons.dbutils.QueryRunner; 7 8 import com.study.util.C3P0Utils; 9 10 public class TransferDao { 11 12 public int inMoney(Connection conn, String inName, double money) throws SQLException { 13 //Connection conn=C3P0Utils.getConnection(); 14 QueryRunner qr=new QueryRunner(); 15 String sql="update account set money=money+? where name=?"; 16 int number=qr.update(conn, sql, inName,money); 17 return number; 18 } 19 20 public int outMoney(Connection conn, String outName, double money) throws SQLException { 21 // Connection conn=C3P0Utils.getConnection(); 22 QueryRunner qr=new QueryRunner(); 23 String sql="update account set money=money-? where name=?"; 24 int number =qr.update(conn, sql, outName,money); 25 return number; 26 } }
DBUtils 事务提交对上面的代码进行了修改:
service层:
public class TransferService { public boolean transfermoney(String inName, String outName, double money) { //调用dao层的inMoney 和 outMoney TransferDao dao=new TransferDao(); Connection conn=null; boolean isTransfer=true; int number1=-1; int number2=-1; try { //开启事务 C3P0Utils.startTransaction(); number1=dao.inMoney(inName ,money); number2=dao.outMoney(outName,money); if (number1==-1 || number2==-1) { //当sql语句的任何一条没有执行成功,就回滚的初始状态 conn.rollback(); } } catch (Exception e) { isTransfer=false; try { C3P0Utils.rollbackTransaction(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally{ try { C3P0Utils.commitTransaction(); //把事务提交,结束,最后把conn返回给连接池 } catch (SQLException e) { e.printStackTrace(); } } return isTransfer; }
dao层:
public class TransferDao { public int inMoney( String inName, double money) throws SQLException { Connection conn=MyC3P0Utils.getCurrenConnection(); QueryRunner qr=new QueryRunner(); String sql="update account set money=money+? where name=?"; int number=qr.update(conn, sql, money,inName); return number; } public int outMoney( String outName, double money) throws SQLException { Connection conn=MyC3P0Utils.getCurrenConnection(); QueryRunner qr=new QueryRunner(); String sql="update account set money=money-? where name=?"; int number =qr.update(conn, sql, money,outName); return number; } }
C3P0Utils 的代码改变:
public class C3P0Utils { private static ComboPooledDataSource dataSource=new ComboPooledDataSource("login"); private static ThreadLocal<Connection > tl=new ThreadLocal<Connection>(); // ThreadLocal 只能存储一个变量 //可TreadLocal<List<Object>> //获取当前线程的连接connection public static Connection getCurrenConnection(){ Connection conn = tl.get(); if (conn==null) { conn=getConnection(); tl.set(conn); } return conn; } //开启事务 public static void startTransaction() throws SQLException{ Connection conn=getCurrenConnection(); conn.setAutoCommit(false); } //回滚事务 public static void rollbackTransaction() throws SQLException{ getCurrenConnection().rollback(); } //提交事务 public static void commitTransaction() throws SQLException{ Connection conn=getCurrenConnection(); conn.commit(); //将Connection从ThreadLocal移除 tl.remove(); conn.close(); } public static DataSource getDataSource(){ return dataSource; } public static Connection getConnection(){ try { return dataSource.getConnection(); } catch (SQLException e) { throw new RuntimeException(e); } } }