首页新闻找找看学习计划

Java在触发事务回滚之后为什么会再一次回到Servlet开始的地方重新走一次流程?

0
悬赏园豆:5 [待解决问题]

代码流程

  1. 前台点击"提交订单"进入BaseServlet.class
  2. BaseServlet.class分发至子类OrderServlet.classsubmitOrder()方法
  3. submitOrder()调用Service层的submitOrder()方法.
  4. 关键是Service层submitOrder()中使用了事务回滚. 这里调用了Dao层两个方法: fun01()fun02(), 其中fun01执行成功, fun02()执行时抛出异常.
  5. catch到异常后, 执行回滚. 然后关闭连接.
    然后, 异常诡异的是, 程序并没有在回滚、关闭连接后结束,而是再一次进入BaseServlet
    再一次执行一次上述流程,而这一次,由于第一次已经将线程绑定的连接关闭了。所以自然出现异常:不能操作已经关闭的连接。
    我的疑惑是:为什么它走了两次这个流程?是因为我调用了个dao层的插入数据的方法吗?
    还是或事物回滚就是从头在执行要一遍流程呢?

这个异常, 导致回滚技术无法实现呀.

代码片段(图片)

代码片段源码

Servlet层

public String submitOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ...

        Debug.log("进入方法:submitOrder...");       // 打印信息
        
        boolean flag = false;
        // 调用service层方法 
        flag = orderService.submitOrder( pids, checkeds, quantitys, user );
        // 提交成功 --> order_info.jsp页面  失败 --> info.jsp
        if( flag ) {
            return goOrderInfoUI(req, resp);
        }else {
            req.setAttribute("error", "提交订单失败!");
            return "/info.jsp";
        }
        
    }

service层

...
// 获得*线程绑定的连接*
        Connection conn = null;
        try {
            conn = C3P0Util.getConnection();
            Debug.log("连接=="+conn);
            // 开启事务
                // 由于插入要么都成功, 要么都失败, 所以需要用事务操作
            Debug.log("进入try");
            conn.setAutoCommit(false);
            Debug.log("开启事务");
            // 调用dao插入数据库
            // 插入订单
            orderDao.insertOrder(order);
            Debug.log("order插入走完");
            // 插入订单项
            orderDao.insertOrderItmes( orderItems );
            
            // 提交事务
            conn.commit();
            
            // 方法返回值为true
            Debug.log("事务已提交");
            flag = true;
        }catch(Exception e) {
            Debug.log("进入外层catch");
            // 回滚事务
            try {
                conn.rollback();
                Debug.log("事务已回滚");
            } catch (SQLException e1) {
                // TODO Auto-generated catch block
                Debug.log("进入内存catch");
                e1.printStackTrace();
            }
        }finally {
            // 关闭连接
            try {
                Debug.log("关闭连接");
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        Debug.log("service走完");
        return flag;
...

注:Debug.log()是自定义方法用来打印信息.

Nisus的主页 Nisus | 初学一级 | 园豆:197
提问于:2017-11-12 13:30
< >
分享
所有回答(2)
0

 个人觉得servlet走第二次流程和事务回滚没有关系;

应该是你多次访问servlet导致的

、熙和 | 园豆:1486 (小虾三级) | 2017-11-13 17:25
0

为啥你service的return不是return true/return false,而是直接return

流年飞雨 | 园豆:1978 (小虾三级) | 2017-11-13 21:21

肯定会回到servlet呀,那里面还有代码呀,正常会执行调用的提交订单后的代码,你可以debug一下,给servlet的提交订单方法打一个断点,给里面的service的提交订单打一个断点,它的下一行代码打一个断点,单步执行看下,还有确保服务器上的代码和本地代码是一致的,如果没问题可能是前台提交了两次订单吧

支持(0) 反对(0) 流年飞雨 | 园豆:1978 (小虾三级) | 2017-11-13 21:33
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册