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

代码流程

  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()是自定义方法用来打印信息.*

1个回答

servlet捕捉到异常后继续往上抛,不知道你控制层通用的异常如何处理的,你直接servlet调用service方法的地方try catch一下试试吧

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问