买书的例子 程序应该将图书数量的操作和更新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 在交易的业务逻辑中进行判断 当用户的账户金额小于购买金额的时候 就取消所作的改变
posted on 2016-12-01 14:46  Sharpest  阅读(330)  评论(0编辑  收藏  举报