0

皆さん、私は複数のテストシステムで動作する次のコードを持っていますが、実稼働システムではNullPointerException. Hibernate は、確実にデータベースに存在するオブジェクトに対して null を返します。これはトランザクション管理が不十分なためだと思いますが、よくわかりません。誰かが問題を見ますか? 以下のコードはすべて、Hibernate ラッパー オブジェクト「db」を使用しています。「db」が作成されたときに、Hibernate のセッション ファクトリから新しいセッションが作成されたため、以下に示すコードのみがそのセッションを使用します。

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 オブジェクトであり、Request オブジェクトと 1 対 1 の外部キー関係があります。つまり、新しい InvalidRequest を作成したときに、Request をパラメーターとして渡したのはそのためです。
  • addObject メソッドは Transaction を使用しますが、getObj は使用しません。これが私の問題に特に重要かどうかはわかりませんが、単なるメモです。
  • Request オブジェクトで evict() などを使用したことがないことに気付くでしょう。これは、Hibernate がそれらをセッション キャッシュにしばらく保存することを意味すると思います。それは私がメモリを使い果たした可能性がありますか?または、キャッシュが大きくなりすぎた場合、Hibernate は自動的にキャッシュをクリアしますか? いずれにせよ、私のコードはすぐに爆撃されたので、これが問題だとは思いませんが、私は肯定的ではありません.
4

1 に答える 1

0

これは古いものですが、偶然見つけたので、Hibernate 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);
}
于 2015-10-27T10:12:37.313 に答える