2

プログラムでアクセスしようとするたびにヌルポインタ例外が発生しますorg.hibernate.envers.entities.mapper.relation.lazy.proxy.ListProxy(つまり、 を呼び出しますlist.size()) が、Eclipse の変数インスペクタを使用してオブジェクトを最初に検査すると、Hibernate が SQL ステートメントを生成し、リストが変更されます。動的に。その後、すべてが機能します。プログラムで同じことを行うにはどうすればよいですか? 試してみましlist.toString()たが、役に立たないようです。

更新 1

これが役立つかどうかはわかりませんが、最初にリスト インスタンスをクリックすると、ディスプレイに次のように表示されます。

com.sun.jdi.InvocationException occurred invoking method.

その後、データベースクエリが実行され、もう一度クリックすると正しい.toString()結果が得られます。

更新 2

これが私が得る元の例外です(デバッグモードで要素を検査しない場合)。

java.lang.NullPointerException
    at org.hibernate.envers.query.impl.EntitiesAtRevisionQuery.list(EntitiesAtRevisionQuery.java:72)
    at org.hibernate.envers.query.impl.AbstractAuditQuery.getSingleResult(AbstractAuditQuery.java:104)
    at org.hibernate.envers.entities.mapper.relation.OneToOneNotOwningMapper.mapToEntityFromMap(OneToOneNotOwningMapper.java:74)
    at org.hibernate.envers.entities.mapper.MultiPropertyMapper.mapToEntityFromMap(MultiPropertyMapper.java:118)
    at org.hibernate.envers.entities.EntityInstantiator.createInstanceFromVersionsEntity(EntityInstantiator.java:93)
    at org.hibernate.envers.entities.mapper.relation.component.MiddleRelatedComponentMapper.mapToObjectFromFullMap(MiddleRelatedComponentMapper.java:44)
    at org.hibernate.envers.entities.mapper.relation.lazy.initializor.ListCollectionInitializor.addToCollection(ListCollectionInitializor.java:67)
    at org.hibernate.envers.entities.mapper.relation.lazy.initializor.ListCollectionInitializor.addToCollection(ListCollectionInitializor.java:39)
    at org.hibernate.envers.entities.mapper.relation.lazy.initializor.AbstractCollectionInitializor.initialize(AbstractCollectionInitializor.java:67)
    at org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy.checkInit(CollectionProxy.java:50)
    at org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy.size(CollectionProxy.java:55)
    at <MY CODE HERE, which checks list.size()>

最終的な解決策 (実際には一時的なハックに近い)

boolean worked = false;
while (!worked) {
    try {
        if(list.size() == 1) {
            // do stuff 
        }
        worked = true;
    } catch (Exception e) {
        // TODO: exception must be accessed or the loop will be infinite
        e.getStackTrace();
    }
}
4

1 に答える 1

4

さて、Hibernate の遅延読み込みが深いアクションで見られます :)

基本的に、hibernate は遅延関連付けされたリレーションのプロキシ クラスをロードします。これにより、クラス C のリストの代わりに、C クラスの Hibernate 自動生成プロキシのリスト (実際には PersistenceBag 実装) が取得されます。これは、実際にアクセスされるまで、関連付けの値のロードを延期する hibernate の方法です。そのため、Eclipse デバッガー (基本的にイントロスペクションを介してインスタンスのフィールド/メソッドにアクセスする) でアクセスすると、必要なデータを取得するための SQL 休止状態トリガーが表示されます。

ここでの秘訣は、怠惰なコレクションにいつアクセスするかによって、異なる結果が得られる可能性があることです。Eclipse デバッガーを使用してアクセスすると、その読み込みを開始した Hibernate セッションにまだいる可能性が高いため、すべてが期待どおりに機能し、ものがアクセスされてデータが読み込まれると、SQL が (遅延して) トリガーされます)。問題は、コード内の同じデータにアクセスしたいが、セッションが既に閉じられている時点で、LazyInitializationException または null を取得することです (後者は、クリーニングにライブラリを使用している場合は、hibenrate プロキシを配置します)ギレアデとして)

于 2011-09-21T17:26:42.167 に答える