使用数据库和URL交互进行并发处理

时间:2015-08-18 05:00:29

标签: java concurrency

我有一个结算应用程序,如果客户已付款,则会在数据库中进行请求检查,如果没有付款,则会点击结算API,然后更新数据库中的响应。

当客户多次发送请求时,我会遇到问题,点击"比尔我"按钮3-4次。所有请求都以毫秒的差异命中服务器。结果,客户多次收费,因为结果没有更新,因为第一个请求需要一些时间,同时第二个请求从数据库中读取状态并再次进行计费。下面是代码。请让我知道我应该采取哪些最佳做法来防止这种情况发生。我试过制作servlet SingleThreadModel,但它没有帮助

 protected void processRequest(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {
    response.setContentType("text/html;charset=UTF-8");
    try (PrintWriter out = response.getWriter()) {
        /* TODO output your page here. You may use following sample code. */
        String mobilenumber = request.getParameter("mobilenumber");
        String param2 = request.getParameter("param2");
        String checkifthecustomerischarged = checkifcharge(mobilenumber);
        if (checkifthecustomerischarged.equals("NOTOK")) {
            String status = hittocharge(mobilenumber, param2);
            int i = updatestatus(mobilenumber, status);
            if (i > 0) {
                out.println("Status Updated ");
            } else {
                out.println("Status Not update Updated ");
            }
        } else {
            out.println("Already Charged");
        }
      }
  }

这里我正在检查表

 private String checkifcharge(String mobilenumber) {
    String st = "NOTOK" ; 
    try {
        Connection conn = null ; 
        ResultSet rs  = conn.createStatement.executeQuery("select sno from table where mobilenumber = "+mobilenumber);
       if(rs.next()){
       st = "OK";
       }

    } catch (Exception e) {
        e.printStackTrace();
     }
  return st ;
  }

这里我正在更新状态

   private int updatestatus(String mobilenumber, String status) {
    int st = 0 ; 
    try {
        Connection conn = getConnection() ; 
       st  = conn.createStatement.executeQuery("update table set status =1    where  mobilenumber ="+mobilenumber);

       releaseConnection(conn);
    } catch (Exception e) {
        e.printStackTrace();
    }
 return st ;
}

1 个答案:

答案 0 :(得分:2)

通常情况下,人们不会只是说"向我收费"但是"特别针对某些事情向我收费" (例如" 2015年8月支付手机号码123")。我会决定每个结算的标识符(例如" 08_2015_123")并将其包含在结算请求和状态表中。然后你可以使用乐观更新,这是

的内容
st=statement.executeQuery("update table set status=1 where identifier='08_2015_123' and status<>1")
// if st==0 it probably means bill was previously payed, don't bill again
顺便说一句,即使您确定无法生成此类标识符,也可以在表单中生成一些虚拟随机字段,这样至少可以识别同一按钮上的多个快速点击(虽然它对更复杂的情况没有帮助,例如忘记他一周前付钱的用户)。但是通过计费,我会努力找到合适的标识符。