在Hibernate代码中抛出异常,是因为事务?

时间:2013-03-22 17:46:32

标签: hibernate transactions

每个人,我都有以下代码可以在多个测试系统上运行,但在生产系统上失败NullPointerException。对于绝对在数据库中的Object,Hibernate返回null。我认为这可能是由于交易管理不善,但我不确定。有没有人看到问题?下面的代码都使用了一个Hibernate包装器对象'db'。当'db'被创建时,从Hibernate的会话工厂创建了一个新的Session,所以只有我在下面显示的代码才会使用该Session。

从Request表中获取所有有效ID的列表。 ID是主键字段:

Criteria criteria = db.getSession().createCriteria(Request.class);
Criterion crit = Restrictions.and(Restrictions.eq("status", "valid"));
criteria.add(crit).setProjection(Projections.property("id"));
List<Integer> results = (List<Integer>)criteria.list();
List<Integer> idList = new ArrayList<Integer>();
for (Integer id : results) idList.add(id);

以下代码抛出NullPointerException。请参阅catch块中的代码注释。辅助方法如下所示:

for (Integer id : idList){
   Request current = null;
   try{
      current = (Request) db.getObj(Request.class, Restrictions.eq("id", id));
      // ... other business logic in here
      InvalidRequest newInvalidRequest = new InvalidRequest(current.getId(), current);
      db.addObject(newInvalidRequest);
    }
    } catch (Exception e){
       //This Exception gets thrown and caught. However the log message never prints.
       //Further along in the code, I get a NullPointerException because
       //the variable 'current' was null and therefore I can't call current.getId()
       //(which is why the log message never printed).
       //but how could current be null when 'id' is in the Request table?
       Log.error("ID = " + current.getId(), e);
    }
}

辅助方法:

public <T> Object getObj(Class<T> clazz, Criterion crit) throws Exception {
   Object object = null;
   try {
      object = session.createCriteria(clazz).add(crit).uniqueResult();
   } catch (Exception e) {
      throw new Exception(e);
   }
   return object;
}

public <T> void addObject(T object) throws Exception {
    try {
        Transaction trans = session.beginTransaction();
        session.save(object);
        trans.commit();
    } catch (Exception e) {
        throw new Exception(e);
    }
}

有些说明:

  • InvalidRequest对象是一个Hibernate对象,它有一个到 与请求对象的一个​​外键关系。换一种说法 这就是为什么当我创建一个新的InvalidRequest时,我传入了 请求作为参数。
  • addObject方法使用Transaction但getObj不使用。我不知道这对我的问题是否有任何特别的意义,但这只是一个注释。
  • 你会注意到我从未在Request对象上使用过evict()或任何东西。我认为这意味着Hibernate会将它们存储在Session缓存中一段时间​​。这是否会使我内存不足?或者,如果它太大,Hibernate会自动清除缓存吗?无论哪种方式,我都不认为这是问题,因为我的代码轰炸得那么快,但我不是正面的。

1 个答案:

答案 0 :(得分:0)

这是一个旧的,但是当我偶然发现它时,它仍然是Hibernate 3的未解决问题。

hibernate标准中的投影与LockMode不兼容, 见https://hibernate.atlassian.net/browse/HHH-3313 所以检查一下你可能有的代码

criteria.setLockMode(your lock mode)

如果像我们一样,你在这里使用一些通用代码来初始化你的标准,我们的代码提取来处理这个问题

CriteriaImpl critiml = (CriteriaImpl) crit;
if (critiml.getProjection() != null) {
    // lock mode is not compatible with projection criteria 
    // see bug entry https://hibernate.onjira.com/browse/HHH-3313
} else {
    crit.setLockMode("obj", LockMode.NONE);
}