Java异常在被捕之后似乎重新出现了

时间:2014-09-17 18:20:23

标签: java hibernate exception

我遇到了一个我不理解的场景。我有以下Web服务(使用下面的一堆伪代码)。

在我的事务管理器类中:

Response HandleRequest(List<Object> myStuff) throws RemoteException   
{ 
    Map<Object, String> problemMap = dataManager.saveMyStuff(myStuff)

    //Nothing here gets executed because HibernateSystemExeption was mysteriously (re)thrown
    log.warn("Step 5");
    if(problemMap.size() > 0)
    {
         //Put problem objects and error messages in response
         return response;
    }
}

然后在我的DataManager类中,我有:

Map<Object, String> saveMyStuff(List<Object> mystuff) 
{
    Session sess = getSession();
    Transaction tx = sess.beginTransaction();
    boolean successful = true;

    Map<Object, String> problems = new HashMap<Object, String>();
    for(Object o : mystuff)
    {
        try
        {
            //Do some hibernate stuff here that throws a HibernateSystemException
        }
        catch(Exception e)
        {
            log.warn("Caught an exeption!", e);
            successful = false;
            log.warn("Step 1");
            problems.put(o, "Couldn't Store object");
            log.warn("Step 2");
        }
    }

    log.warn("Step 3");
    try
    {
        if(successful)
            tx.commit;
       else
            tx.rollback();
    }
    catch(Exception e)
    {
        log.warn("Another Exception caught!", e);
    }

    log.warn("Step 4");
    return problems;
}

如果异常在datamanager中成功捕获,我会在日志文件中看到它。代码进入return语句。但是,当它从数据管理器返回时,我在事务管理器中获得了SAME异常,好像它从未被数据管理器捕获,并且该异常作为远程异常而不是响应传递回用户raw。调用saveMyStuff后,事务管理器中没有任何内容被执行。这就好像异常保留在堆栈上,直到方法返回,然后再次抛出,即使它已在datamanager中处理。有没有人见过这样的事情,或者知道会发生什么?

编辑:经过一些实验后,似乎问题与它是HibernateSystemException这一事实有关。如果我抛出一个通用的Exception作为测试,代码就像我期望的那样工作。那么HibernateSystemException会导致这种奇怪的行为呢?

编辑2:我按照建议完成并将事务提交/回滚包装在try / catch中。异常仍然会将其返回给用户。我还添加了调试打印语句。在日志中我看到步骤1-4打印但不是5.我也没有看到从事务提交/回滚块中捕获异常。

3 个答案:

答案 0 :(得分:1)

您描述的内容与Java异常处理逻辑不匹配。因此,发生了一些不同的事情,例如tx.rollback()可能抛出异常。尝试在try-catch中包含回滚并处理异常。

答案 1 :(得分:0)

我之前的回答是不正确的,所以新的代码。我建议另一个尝试catch块,以确保没有抛出第二个异常。

Map<Object, String> saveMyStuff(List<Object> mystuff) 
{
    Session sess = getSession();
    Transaction tx = sess.beginTransaction();
    boolean successful = true;

    Map<Object, String> problems = new HashMap<Object, String>();
    for(Object o : mystuff)
    {
        try
        {
            //Do some hibernate stuff here that throws a HibernateSystemException
        }
        catch(Exception e)
        {
            log.warn("Caught an exeption!", e);
            successful = false;
            problems.put(o, "Couldn't Store object");
        }
    }



  try
        {
            if(successful)
               tx.commit;
             else
               tx.rollback();
        }
        catch(Exception e)
        {
            log.warn("Caught an exeption!", e);
            problems.put(o, "Couldn't Store object");
        }

    return problems;
}

答案 2 :(得分:0)

好的,我发现了问题。由于我在调用getSession而不是openSession时,会在方法返回时隐式刷新会话。刷新会话的行为导致抛出第二个异常。我通过在返回之前显式刷新会话并在try / catch中包围它来确认这一点。这抓住了异常但是当会话在返回时再次刷新时仍然被抛出。最终的解决方法是调用openSession并使用try catch块围绕会话刷新。

DataManager类:

Map<Object, String> saveMyStuff(List<Object> mystuff) 
{
    Session sess = getSessionFactory.openSession();
    Transaction tx = sess.beginTransaction();
    boolean successful = true;

    Map<Object, String> problems = new HashMap<Object, String>();
    for(Object o : mystuff)
    {
        try
        {
            //Do some hibernate stuff here that throws a HibernateSystemException
        }
        catch(Exception e)
        {
            log.warn("Caught an exeption!", e);
            successful = false;
            problems.put(o, "Couldn't Store object");
        }
    }

    try
    {
       if(successful)
            tx.commit;
       else
            tx.rollback();

        sess.flush();
    }
    catch(Exception e)
    {
        log.warn("Another Exception caught!", e);
    }
    finally
    {
        sess.close();
    }

    return problems;
}

感谢大家的帮助!