日期:2014-05-17  浏览次数:20800 次

关于请求并发的问题
我有个action方法是取消订单用的

在取消之前先判断订单状态是不是已取消

不是的话就改成已取消并且把订单的钱加到账户

但是测试的时候 连续快速的点两次取消

钱加了两次  

有可能是什么原因引起的

是两次请求同时执行了?
action
先查询订单状态 判断是否已取消
然后
boolean res = this.ordersManager.cancelOrder(uporders);


dao层
Java code

public boolean cancelOrder(Orders orders) throws DataAccessException {
        Session session =null;
        Transaction tx = null;
        Balance bal = null;
        try{
            session = hibernateTemplate.getSessionFactory().openSession();
            tx = session.beginTransaction();
            
            
            
            ClientLoginInfo clientLoginInfo = orders.getClientLoginInfo();
            String manualName=orders.getClientLoginInfo().getClientUserName();
            double money=orders.getSumMoney();
            
            Company c = orders.getClientLoginInfo().getCompany();
            Integer companyId = c.getCompanyId();
            List list = this.hibernateTemplate.find(
                    "from Balance as g where g.company.companyId=?", companyId);
            if (list.isEmpty()) {
                bal = new Balance();
                bal.setCompany(c);
                bal.setBalanceMoney(money);
                session.save(bal);        
            } else {
                 bal= (Balance) list.get(0);
                bal.setBalanceMoney(bal.getBalanceMoney()
                        + money);
                session.merge(bal);
            }
                           session.merge(orders);
            
            tx.commit();
            return true;
        }catch (DataAccessException e) {
            tx.rollback();
            e.printStackTrace();
            throw e;
        }finally{
            if(session!=null)
                session.close();
        }
    }



------解决方案--------------------
连续点了两次取消,这应该是属于重复提交的问题吧."取消"的按钮点了两次,这个按钮触发的也是提交表单的操作,相当于提交了两次表单.Struts里面是有处理重复提交的机制的,需要用到"令牌"机制.
------解决方案--------------------
cancelOrder(Orders orders)多个线程同时操作orders,必然会引发线程安全问题。
这么弄:
cancelOrder(Orders orders){
synchronized(orders){
********
}
}


------解决方案--------------------
这个和那些常见的重复提交的情况类似啊

你的订单状态查询不足以阻止重复提交,原因应该是两次提交间隔太短,状态还没来得及改变

最直接的应该是点击过的按钮要设置成无法再次点击直至有返回结果
------解决方案--------------------
失效的,但你可以针对class同步
Java code

public static void main(String[] args) {
        synchronized (Test.class) {
            //you code here
        }
    }