延迟的ObjectNotFoundException

时间:2013-10-20 22:10:42

标签: java hibernate

使用:Hibernate 4.2.3,Eclipse Juno和JSR286 portlet

我遇到了一个我不理解的异常行为,任何想法或建议都会受到高度赞赏。

我第一次使用特定的数据库表(具有遗留数据)我需要检查是否存在外键控制的父记录,如果不存在,那么我想插入一个虚拟父记录,之后一切将工作 - 我不想继续检查父记录,所以我在语句周围放入一个try / catch块,如果父项不存在,将导致ObjectNotFoundException。我知道有一个丢失的父记录会导致此异常,因为一旦插入父记录,错误就会消失。

我需要帮助的问题是,在 退出方法块之后不会抛出异常,并且它不会被try / catch块捕获,这是我需要的地方。< / p>

public List<Folder> getFolders(Long folderId) {
String hql = "select folder from Folder folder where folder.folderId=:folderId order by folder.folderId";
Boolean valid = false;
List<Folder> folder = new ArrayList<Folder>();
while (!valid) {
  try {
    folder = (List<Folder>) sessionFactory
       .getCurrentSession()
       .createQuery(hql)
       .setLong("folderId", folderId)
       .list();
   valid = true;
} catch (ObjectNotFoundException e) {
try {
    sessionFactory
    .getCurrentSession()
    .createSQLQuery("INSERT INTO `folder` (`folderId`) VALUES (0);")
    .executeUpdate();
    logger.info("added parent record 0 to folder table");
    } catch (Exception e1) {
      logger.info(e1.getMessage());
      }
    }
  }
return folder;

}

修改 这是堆栈跟踪 - 正如您所看到的,Hibernate会发出警告,然后下一个错误来自Spring DispatcherPortlet,而不是来自我自己的任何代码。

2013-10-20 23:15:07,438 WARN [org.hibernate.engine.loading.internal.LoadContexts] - HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@a5571f9<rs=com.mchange.v2.c3p0.impl.NewProxyResultSet@417e79d3>
2013-10-20 23:15:07,438 WARN [org.hibernate.engine.loading.internal.CollectionLoadContext] - HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries
2013-10-20 23:15:07,438 WARN [org.hibernate.engine.loading.internal.LoadContexts] - HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@6fad97bb<rs=com.mchange.v2.c3p0.impl.NewProxyResultSet@5d4fab2d>
2013-10-20 23:15:07,438 WARN [org.hibernate.engine.loading.internal.CollectionLoadContext] - HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries
2013-10-20 23:15:07,438 WARN [org.springframework.web.portlet.DispatcherPortlet] - Handler execution resulted in exception - forwarding to resolved error view
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.sbeko.slider.domain.Folder#10207]
    at org.hibernate.internal.SessionFactoryImpl$1$1.handleEntityNotFound(SessionFactoryImpl.java:244)
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:212)

1 个答案:

答案 0 :(得分:1)

来自Hibernate ObjectNotFoundException javadoc:

  

当Session.load()无法选择具有给定的行时抛出   主键(标识符值)。可能不会抛出此异常   当调用load()时,即使数据库上没有行,   因为load()会尽可能返回代理。应用应该使用   Session.get()用于测试数据库中是否存在行。

所以有两件事需要检查:如果你有惰性实例化,并且因此获得代理而不是真实对象并在实际使用真实对象的位置获取异常,以及是否session.get()将解决您的问题,甚至更好地满足您的目的。


编辑以处理更多问题:

使用HQL在another SO question中找到了这个:

public Boolean exists (DTOAny instance) 
{
    Query query = getSession().             
    createQuery("select 1 from DTOAny t where t.key = :key");
        query.setString("key", instance.getKey() );
    return (query.uniqueResult() != null);
}

您可以将instance.getKey()替换为您需要的任何内容,以获取您要查找的实例的ID。

另外,如果你要使用你提到的get()方法,我认为它需要实际的索引ID,而不是0.祝你好运。