2013-03-22 73 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); 
} 
相關問題