转账时必须双方同时成功,要么同时失败,就是把双方组成单元放到事务中
1)显示的开启一个事务:start transaction
2)事务提交:commit代表从开启事务到事务提交 中间的所有的sql都认为有效 真正的更新数据库
3)事务的回滚:rollback 代表事务的回滚 从开启事务到事务回滚 中间的所有的 sql操作都认为无效数据库没有被更新
一、JDBC事务操作
默认是自动事务:
执行sql语句:executeUpdate() ---- 每执行一次executeUpdate方法 代表 事务自动提交
通过jdbc的API手动事务:
开启事务:conn.setAutoComnmit(false);
提交事务:conn.commit();
回滚事务:conn.rollback();
注意:控制事务的connnection必须是同一个
执行sql的connection与开启事务的connnection必须是同一个才能对事务进行控制
一、事务的特性和隔离级别(概念性问题---面试)
事务的特性ACID
? 1)原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作 要么都发生,要么都不发生。
? 2)一致性(Consistency)一个事务中,事务前后数据的完整性必须保持一致。
? 3)隔离性(Isolation)多个事务,事务的隔离性是指多个用户并发访问数据库时, 一个用户的 事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
? 4)持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变 就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
转账功能
//jsp <form action="${pageContext.request.contextPath }/ZhuanzhangServlet" method="post"> 转入账户<input type="text" name="in"><br> 转除账户<input type="text" name="out"><br> 金额<input type="text" name="money"><br> <input type="submit" name="转账"> </form>
public class ZhuanzhangServlet extends HttpServlet { private AccService accService=new AccService(); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); //获取三个参数 String out=request.getParameter("out"); String in=request.getParameter("in"); String moneyStr=request.getParameter("money"); double money=Double.parseDouble(moneyStr);//字符串转Double int row=accService.transfer(out, money, in); //解决响应 response.setContentType("text/html;charset=UTF-8"); if(row>0){ response.getWriter().write("转账成功"); }else{ response.getWriter().write("转账失败"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
public class AccDao { //转出 public int outMoney(Connection conn,String out,double money) throws SQLException{ QueryRunner qr=new QueryRunner(); String sql="update account set money=money-? where name=?"; int row=qr.update(conn,sql,money,out); return row; } public int inMoney(Connection conn,String in,double money) throws SQLException{ QueryRunner qr=new QueryRunner(); String sql="update account set money=money+? where name=?"; int row=qr.update(conn,sql,money,in); return row; } }
public class AccService { private AccDao accDao=new AccDao(); //转出(转账方法) public int transfer(String out,double money,String in){ int row=0; int row1=0; Connection conn=null; try { //获取连接对象 conn=MyDBUtils.getConn(); //开启事务 conn.setAutoCommit(false); row=accDao.outMoney(conn,out, money); int y=1/0; row1=accDao.inMoney(conn,in, money); } catch (Exception e) { //回滚 try { conn.rollback(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); } finally{ try { //提交事务 conn.commit(); conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(row>0&&row1>0){ return 1; }else{ return 0; } } }