JPA:处理OptimisticLockException的模式

时间:2011-06-30 22:03:38

标签: java database jpa

在(REST)Web服务中处理OLE的正确模式是什么?这就是我现在正在做的事情,例如,

protected void doDelete(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    ...
    ...
    ...

    try {
        try {
            em.getTransaction().begin();
            // ... remove the entity
            em.getTransaction().commit();
        } catch (RollbackException e) {
            if (e.getCause() instanceof OptimisticLockException) {
                try {
                    CLog.e("optimistic lock exception, waiting to retry ...");
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                }
                doDelete(request, response);
                return;
            }
        }

        // ... write response

    } catch (NoResultException e) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
        return;
    } finally {
        em.close();
    }
}

每当你在代码中看到睡眠时,很有可能它是不正确的。有没有更好的方法来处理这个?

另一种方法是立即将故障发送回客户端,但我宁愿不让他们担心。正确的事情似乎做了使服务器上的请求成功所需的一切,即使它需要一段时间。

感谢。

4 个答案:

答案 0 :(得分:23)

静止的“政治正确”答案是返回一个HTTP 409(冲突)女巫与乐观锁定的想法完全匹配。您的客户应该管理它,可能需要几秒钟后重新开始。

我不会在您的应用中添加重试逻辑,因为您的客户端已经处理了返回40X代码的情况。

答案 1 :(得分:18)

如果您获得乐观锁定异常,则表示某些其他事务对您尝试更新/删除的实体进行已提交更改。由于另一个事务已经提交,因此立即重试可能很有可能成功。

我也会在N次尝试后使方法失败,而不是等待StackOverflowException发生。

答案 2 :(得分:1)

顺便说一句,catch (InterruptedException e) {}总是一个坏主意,因为系统已经要求你的计算取消,你忽略了它。在Web服务的上下文中,InterruptedException是向客户端发出错误信号的另一个好理由。

答案 3 :(得分:0)

如果您只是继续重试直到它仍然有效,为什么不禁用乐观锁?您应该让来电者知道他们是根据过时的信息做出决定的!如果您控制双方,则可以返回适当的400代码。如果它是公开的,那么任意客户只需返回500便可能更友好。(当然,你会使适当的响应代码使用不足!这样的困境)