Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2307519
  • 博文数量: 252
  • 博客积分: 5472
  • 博客等级: 大校
  • 技术积分: 3107
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-17 18:39
文章分类

全部博文(252)

文章存档

2012年(96)

2011年(156)

分类: Java

2011-12-08 16:53:11

买书的例子 程序应该将图书数量的操作和更新account用户余额的操作作为一个事务来处理,只有这两个操作都完成的情况下,才能提交事务,否则就回滚事务。
 
1  buy.html
  1. <html>
  2.     <head>
  3.         <title>购买图书</title>
  4.     </head>
  5.     <body>
  6.         购买《Servlet/JSP深入详解》<p>
  7.         <form action="trade" method="post">
  8.             输入用户名:&nbsp;&nbsp;<input type="text" name="userid"><br>
  9.             输入购买数量:<input type="text" name="quantity"><p>
  10.             <input type="reset" value="重填">
  11.             <input type="submit" value="购买">
  12.         </form>
  13.     </body>
  14. </html>
2  TradeServlet.java
 
  1. package servlet;

  2. import javax.servlet.*;
  3. import java.io.*;
  4. import javax.servlet.http.*;
  5. import java.sql.*;

  6. public class TradeServlet extends HttpServlet
  7. {
  8.     private String url;
  9.     private String user;
  10.     private String password;
  11.     
  12.     public void init() throws ServletException
  13.     {
  14.         ServletContext sc=getServletContext();
  15.         String driverClass=sc.getInitParameter("driverClass");
  16.         url=sc.getInitParameter("url");
  17.         user=sc.getInitParameter("user");
  18.         password=sc.getInitParameter("password");
  19.         try
  20.         {
  21.             Class.forName(driverClass);
  22.         }
  23.         catch(ClassNotFoundException ce)
  24.         {
  25.             throw new ServletException("加载数据库驱动失败!");
  26.         }
  27.     }
  28.     
  29.     public void doGet(HttpServletRequest req, HttpServletResponse resp)
  30.                throws ServletException,IOException
  31.     {
  32.         Connection conn=null;
  33.         Statement stmt=null;
  34.         PreparedStatement pstmt=null;
  35.         ResultSet rs=null;
  36.         
  37.         resp.setContentType("text/html;charset=gb2312");
  38.         PrintWriter out=resp.getWriter();
  39.         
  40.         req.setCharacterEncoding("gb2312");
  41.         
  42.         String userid=req.getParameter("userid");
  43.         String quantity=req.getParameter("quantity");
  44.         
  45.         if(null==userid || userid.equals("") ||
  46.            null==quantity || quantity.equals(""))
  47.         {
  48.             
  49.             out.println("错误的请求参数");
  50.             out.close();
  51.         }
  52.         else
  53.         {
  54.             try
  55.             {
  56.                 conn=DriverManager.getConnection(url,user,password);
  57.                 
  58.                 conn.setAutoCommit(false);
  59.                 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
  60.                 
  61.                 stmt=conn.createStatement();
  62.                 rs=stmt.executeQuery("select price,amount from bookinfo where id=3");
  63.                 rs.next();
  64.                 float price=rs.getFloat(1);
  65.                 int amount=rs.getInt(2);
  66.                 
  67.                 int num=Integer.parseInt(quantity);
  68.                 if(amount>=num)
  69.                 {
  70.                     pstmt=conn.prepareStatement("update bookinfo set amount = ? where id = 3");
  71.                     pstmt.setInt(1,amount-num);
  72.                     pstmt.executeUpdate();
  73.                 }
  74.                 else
  75.                 {
  76.                     out.println("您所购买的图书库存数量不足。");
  77.                     out.close();
  78.                     return;
  79.                 }
  80.                 pstmt=conn.prepareStatement("select balance from account where userid = ?");
  81.                 pstmt.setString(1,userid);
  82.                 rs=pstmt.executeQuery();
  83.                 
  84.                 rs.next();
  85.                 float balance=rs.getFloat(1);
  86.                 
  87.                 float totalPrice=price*num;
  88.                 
  89.                 if(balance>=totalPrice)
  90.                 {
  91.                     pstmt=conn.prepareStatement("update account set balance = ? where userid = ?");
  92.                     pstmt.setFloat(1,balance-totalPrice);
  93.                     pstmt.setString(2,userid);
  94.                     pstmt.executeUpdate();
  95.                 }
  96.                 else
  97.                 {
  98.                     conn.rollback();
  99.                     out.println("您的余额不足。");
  100.                     out.close();
  101.                     return;
  102.                 }
  103.                 conn.commit();
  104.                 out.println("交易成功!");
  105.                 out.close();
  106.             }
  107.             catch(SQLException se)
  108.             {
  109.                 if(conn!=null)
  110.                 {
  111.                     try
  112.                     {
  113.                         conn.rollback();
  114.                     }
  115.                     catch(SQLException ***)
  116.                     {
  117.                         ***.printStackTrace();
  118.                     }
  119.                 }
  120.                 se.printStackTrace();
  121.             }
  122.             finally
  123.             {
  124.                 if(rs!=null)
  125.                 {
  126.                     try
  127.                     {
  128.                         rs.close();
  129.                     }
  130.                     catch(SQLException se)
  131.                     {
  132.                         se.printStackTrace();
  133.                     }
  134.                     rs=null;
  135.                 }
  136.                 if(stmt!=null)
  137.                 {
  138.                     try
  139.                     {
  140.                         stmt.close();
  141.                     }
  142.                     catch(SQLException se)
  143.                     {
  144.                         se.printStackTrace();
  145.                     }
  146.                     stmt=null;
  147.                 }
  148.                 if(pstmt!=null)
  149.                 {
  150.                     try
  151.                     {
  152.                         pstmt.close();
  153.                     }
  154.                     catch(SQLException se)
  155.                     {
  156.                         se.printStackTrace();
  157.                     }
  158.                     pstmt=null;
  159.                 }
  160.                 if(conn!=null)
  161.                 {
  162.                     try
  163.                     {
  164.                         conn.close();
  165.                     }
  166.                     catch(SQLException se)
  167.                     {
  168.                         se.printStackTrace();
  169.                     }
  170.                     conn=null;
  171.                 }
  172.             }
  173.         }
  174.     }
  175.     
  176.     public void doPost(HttpServletRequest req, HttpServletResponse resp)
  177.                throws ServletException,IOException
  178.     {
  179.         doGet(req,resp);
  180.     }
  181. }
 
 
1  44、45行 调用请求对象的getParameter()方法得到用户名和购买图书的数量
 
2  60行 调用Connection对象的setAutoCommit()方法 传递 false参数 取消自动提交
 
3  61行 调用Connection对象的setTransactionIsolation()方法设置事务的隔离等级为Repeatable Read
 
4  99行 如果用户的余额不足 那么这次交易失败 调用Connection的rollback()方法,回到交易开始之前的状态,也就是回到bookinfo表中书的书目没发生改变的时候
 
注意: 如果在调用rollback()方法之前调用了commit()方法,那么只能回滚到上一次调用commit()方法之后所作的改变
 
5  104行 若果所有的操作都成功了 调用Connection对象的commit()方法提交事务,也就是向数据库提交所有的改变
 
6  在交易过程中,若果发生了异常 那么就在114行 调用Connection对象的rollback()方法回滚所有的改变
 
 
上面这个servlet用到了两种方式保证交易的正常进行
 
1 利用异常处理机制 一旦交易过程发生异常 就取消所有的改变
2 在交易的业务逻辑中进行判断 当用户的账户金额小于购买金额的时候 就取消所作的改变
阅读(24926) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~