Nisus-LJ 2017-11-12 05:35 采纳率: 0%
浏览 1081

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条回答 默认 最新

  • wb_snail 2017-11-23 09:29
    关注

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

    评论

报告相同问题?

悬赏问题

  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型
  • ¥15 求学软件的前人们指明方向🥺