0

使用:Hibernate 4.2.3、Eclipse Juno 和 JSR286 portlet

我得到一个我不理解的异常行为,任何想法或建议将不胜感激。

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

我需要帮助的问题是直到退出方法块后才会抛出异常,并且它不会被 try/catch 块捕获,这正是我需要的地方。

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)
4

1 回答 1

1

从休眠 ObjectNotFoundException javadoc:

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

所以有两件事要检查:如果你有惰性实例化,因此得到一个代理而不是一个真实的对象,并在实际使用真实对象的时候得到异常,以及 session.get() 是否会解决你的问题,甚至更好地服务于你的目的。


编辑以处理更多问题:

使用 HQL在另一个 SO 问题中发现了这一点:

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。祝您好运。

于 2013-10-20T22:31:15.860 回答