2013-03-22 76 views
0

大家,我有以下代码适用于多个测试系统,但失败,那么生产系统与NullPointerException上。 Hibernate肯定会在数据库中返回null。我认为这可能是由于交易管理不善,但我不确定。有没有人看到一个问题?下面的代码都使用Hibernate包装对象'db'。当创建'db'时,从Hibernate的会话工厂创建了一个新会话,因此只有我的代码如下所示使用该会话。在Hibernate代码中抛出异常,是因为事务吗?

获取从申请表中的所有有效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太大,Hibernate会自动清除缓存吗?无论哪种方式,我不认为这是问题,因为我的代码轰炸如此之快,但我不积极。
+0

你能在getObj赶超块添加记录? – anstarovoyt 2013-03-22 19:10:21

+0

@Andrew谢谢你看看。我无法在生产中再次部署这一段时间(几个月)。它在三台测试机器中的任何一台上进行测试时不会抛出异常。我并不确定如何继续,或者为什么Hibernate会抛出一个异常,因为我所做的只是读取和插入带有FK的(新)对象到我读入数据库的对象。在测试中,当我从数据库中删除对象后,我只能够复制空指针异常,因为它已经被添加到idList中。然而,这不会发生在生产上;我们不会从该表中删除。 – KyleM 2013-03-22 19:14:38

+0

你确定这个ID是唯一的吗? – anstarovoyt 2013-03-22 19:23:14

回答

0

这是一个古老的一个,但我偶然发现它和国际海事组织它仍然是休眠的未开放的问题3.

在休眠的标准投影与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); 
} 
相关问题