Hibernate-reactive: 例はORM5.4.24で失敗します

作成日 2020年11月20日  ·  37コメント  ·  ソース: hibernate/hibernate-reactive

org.hibernate:hibernate-core:5.5.0-SNAPSHOT:20201117.201048-196を使用したログの1つの例:

Feersum Endjinn is a great book!
[ERROR] failed to execute statement [select author0_.id as id1_0_0_, author0_.name as name2_0_0_ from authors author0_ where author0_.id in (?,?)]
[ERROR] could not load an entity batch: [org.hibernate.example.reactive.Author#<1, 3>]
java.util.concurrent.CompletionException: org.hibernate.LazyInitializationException: Collection cannot be initialized: org.hibernate.example.reactive.Author.books
    at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273) ~[?:1.8.0_275]
    at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280) ~[?:1.8.0_275]
    at java.util.concurrent.CompletableFuture.uniAccept(CompletableFuture.java:673) ~[?:1.8.0_275]
    at java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:683) ~[?:1.8.0_275]
    at java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2010) ~[?:1.8.0_275]
    at java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:110) ~[?:1.8.0_275]
    at org.hibernate.reactive.loader.ReactiveLoaderBasedResultSetProcessor.reactiveInitializeEntitiesAndCollections(ReactiveLoaderBasedResultSetProcessor.java:150) ~[hibernate-reactive-core-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT]
    at org.hibernate.reactive.loader.ReactiveLoaderBasedResultSetProcessor.reactiveExtractResults(ReactiveLoaderBasedResultSetProcessor.java:83) ~[hibernate-reactive-core-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT]
Error: Exception in thread "main" java.util.concurrent.CompletionException: org.hibernate.LazyInitializationException: Collection cannot be initialized: org.hibernate.example.reactive.Author.books
    at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
    at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
    at org.hibernate.reactive.loader.ReactiveLoader.reactiveProcessResultSet(ReactiveLoader.java:123) ~[hibernate-reactive-core-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT]
    at org.hibernate.reactive.loader.ReactiveLoader.lambda$doReactiveQueryAndInitializeNonLazyCollections$0(ReactiveLoader.java:71) ~[hibernate-reactive-core-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT]
    at java.util.concurrent.CompletableFuture.uniCompose(CompletableFuture.java:966) ~[?:1.8.0_275]
    at java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:940) ~[?:1.8.0_275]
    at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488) ~[?:1.8.0_275]
    at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1975) ~[?:1.8.0_275]

...

Caused by: org.hibernate.LazyInitializationException: Collection cannot be initialized: org.hibernate.example.reactive.Author.books
    at org.hibernate.reactive.session.impl.ReactiveSessionImpl.initializeCollection(ReactiveSessionImpl.java:320)
    at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:589)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:264)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
bug

全てのコメント37件

おっと、その通りです。 @ Sanneと私は、CIの他の誤った障害のために、これを見逃しました。

これは#443に関連していると推測するのは危険です。

その問題はDirtyCheckingに関連していますか?
問題はこれに関連していると思います: https

とにかく、それはORM5.4.24へのアップデート後に起こります

その問題はDirtyCheckingに関連していますか?

さて、バグはバッチロードに関連していると思いました。 私は間違っているかもしれません。

その問題はDirtyCheckingに関連していますか?

さて、バグはバッチロードに関連していると思いました。 私は間違っているかもしれません。

まあ、それは私が間違っているように見えます、そして問題は確かに他の場所にあります。

私はテストケースに取り組んでいます。 うまくいけば、私はこれをすぐに確認できるでしょう。

ただし、例だけが失敗し、バイトコードの拡張を有効にする唯一の場所であるため、それは理にかなっています。

OK、素晴らしい。

あ、はい。 問題は、バイトコード拡張が有効になっている場合のコレクションのダーティチェックです。 以前はなぜ機能していたのかわかりません。 おそらく、 ORMのこのバグが問題を隠していたので、修正されたのでわかります。

うーん、なんてピタ。

OTOH、まだCollectionPersisterがないのに、コレクションが_matter_でさえダーティチェックをしているのはなぜですか?

これが問題です:

拡張メソッド$$_hibernate_hasDirtyAttributesがから変更されました

    public boolean $$_hibernate_hasDirtyAttributes() {
        boolean var1 = false;
        var1 = this.$$_hibernate_tracker != null && !this.$$_hibernate_tracker.isEmpty();
        return var1;
    }

    public boolean $$_hibernate_hasDirtyAttributes() {
        boolean var1 = false;
        var1 = this.$$_hibernate_tracker != null && !this.$$_hibernate_tracker.isEmpty() || this.$$_hibernate_areCollectionFieldsDirty();
        return var1;
    }

    public boolean $$_hibernate_areCollectionFieldsDirty() {
        boolean var1 = false;
        if (!var1 && this.$$_hibernate_collectionTracker != null) {
            if (this.movies == null && this.$$_hibernate_collectionTracker.getSize("movies") != -1) {
                var1 = true;
            } else if (this.movies != null && this.$$_hibernate_collectionTracker.getSize("movies") != this.movies.size()) {
                var1 = true;
            }
        }

        return var1;
    }

this.movies.size()を呼び出すと、 LazyInitializationException

moviesは、私が作成したテスト内の関連付けの名前です

@DavideDでは、ここで起こっているのは、透過的なレイジーinitがない(つまり、 fetch()への呼び出しがない)ということだと思いますか、それとももっと深いものですか?

@DavideD https://github.com/hibernate/hibernate-orm/pull/3645にコメントしましたsize()への呼び出しが私には正しく見えないためです。 (しかし、私は簡単に何かを見逃している可能性があります。)

@DavideDでは、ここで起こっているのは、透過的なレイジーinitがない(つまり、fetch()の呼び出しがない)ということだと思いますか、それとももっと深いものですか?

それが問題だと思います。 コレクションが既にフェッチされるように、どこかでコレクションをフェッチできるかどうかを確認しようとしています。
ちなみに、EAGERフェッチの関連付けを設定すると、すべてが機能します。

コレクションが既にフェッチされるように、どこかでコレクションをフェッチできるかどうかを確認しようとしています。

OKですが、要素をダーティチェックするためだけにmappedByとのフェッチされていない関連付けをフェッチしているのは私にはまだ間違っていると感じているので、その_今_で自殺しないでください。 @beikov@Sanneが何を言わ

(OTOH、コアが_この特定のケースで_正しいことをしていない場合でも、他のケースでは作業中の修正が必要になる場合があります。)

ありがとう@gavinking

映画コレクションが!= nullなのはなぜですか? 私はこれをコアで再現しようとしましたが、怠惰な場合、そのようなコレクションがnull以外になることは決してないため、再現できませんでした。

さて、どこかでちょっと長い議論があったことを思い出します。 私が開いた問題は、この「二重怠惰」またはコレクションがHibernate ORMで少なくとも間違いなく悪いことであり、フェッチが透過的でないHRにとってははるかに悪い問題であると主張したところです。 コレクションへの参照を取得して、コレクションでfetch()を呼び出す必要があります。

OKが見つかりました。 それで、これは#374に関連している可能性がありますか?

RXではcollectionsInDefaultFetchGroupEnabled常に真ですか?

うーん、trueに設定すると、コレクションは熱心に初期化されます。

RXではcollectionsInDefaultFetchGroupEnabled常に真ですか?

ええ、そうです。

うーん、trueに設定すると、コレクションは熱心に初期化されます。

うーん...本当に? それは意図ではありませんでした!

collectionsInDefaultFetchGroupEnabledは、デフォルトのフェッチグループにコレクションプロキシを含めることになっています。 コレクション自体を実際にフェッチすることは想定されていません。

それで、私は完全に失敗したか、そのコードを書いた後に何かが変わった。

エンハンスメントへの現在のアプローチは理想的ではなく、フィールドを永続コレクションに初期化する必要があることを私はあなたと一緒にしていますが、RXで発生している問題は他の何かが原因である可能性があると思います。 フラグをtrueに設定すると、次のトレースを通じてコレクションが初期化されていることがわかります。

org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
org.hibernate.collection.internal.AbstractPersistentCollection$1.doWork(AbstractPersistentCollection.java:178)
org.hibernate.collection.internal.AbstractPersistentCollection$1.doWork(AbstractPersistentCollection.java:163)
org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:264)
org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:162)
org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:371)
org.hibernate.test.bytecode.enhancement.dirty.DirtyTrackingCollectionTest$StringsEntity.$$_hibernate_removeDirtyFields(DirtyTrackingCollectionTest.java)
org.hibernate.test.bytecode.enhancement.dirty.DirtyTrackingCollectionTest$StringsEntity.$$_hibernate_clearDirtyCollectionNames(DirtyTrackingCollectionTest.java)
org.hibernate.test.bytecode.enhancement.dirty.DirtyTrackingCollectionTest$StringsEntity.$$_hibernate_clearDirtyAttributes(DirtyTrackingCollectionTest.java)
org.hibernate.tuple.entity.PojoEntityTuplizer.afterInitialize(PojoEntityTuplizer.java:228)
org.hibernate.persister.entity.AbstractEntityPersister.afterInitialize(AbstractEntityPersister.java:5093)
org.hibernate.engine.internal.TwoPhaseLoad.afterInitialize(TwoPhaseLoad.java:405)
org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.afterInitialize(AbstractRowReader.java:271)
org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:214)
org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:96)
org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:105)
org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:285)
org.hibernate.persister.entity.AbstractEntityPersister.doLoad(AbstractEntityPersister.java:4441)
org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4431)
org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:569)
org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:537)
org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208)
org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:332)
org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:121)
org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1186)
org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1175)
org.hibernate.internal.SessionImpl.access$2100(SessionImpl.java:193)
org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2786)
org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.lambda$load$1(SessionImpl.java:2767)
org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.perform(SessionImpl.java:2723)
org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2767)
org.hibernate.internal.SessionImpl.find(SessionImpl.java:3322)
org.hibernate.internal.SessionImpl.find(SessionImpl.java:3284)
org.hibernate.test.bytecode.enhancement.dirty.DirtyTrackingCollectionTest.lambda$test$1(DirtyTrackingCollectionTest.java:57)
org.hibernate.testing.transaction.TransactionUtil.doInJPA(TransactionUtil.java:235)
org.hibernate.testing.transaction.TransactionUtil.doInJPA(TransactionUtil.java:276)
org.hibernate.test.bytecode.enhancement.dirty.DirtyTrackingCollectionTest.test(DirtyTrackingCollectionTest.java:56)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45)
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:298)
org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:292)
java.util.concurrent.FutureTask.run(FutureTask.java:266)
java.lang.Thread.run(Thread.java:748)

したがって、 $$_hibernate_removeDirtyFields()は、初期化されていないコレクションでsize()を呼び出しています。 _すべき_でしょうか?

エンハンスメントへの現在のアプローチは理想的ではなく、フィールドを永続コレクションに初期化する必要があることを私はあなたと一緒にしていますが、RXで発生している問題は他の何かが原因である可能性があると思います。 フラグをtrueに設定すると、次のトレースを通じてコレクションが初期化されていることがわかります。

私はおそらく何かが足りないのですが、これは同じ問題ではありませんか?
まだsize()呼び出していますが、別のメソッドからです

あなたが正しいです。 どうやら、コレクションはこの問題の原因となる怠惰なものとして登録されていません。 現在調査中です。

これらの問題を修正する必要があるPRは次のとおりです: https

@beikovに感謝し

@beikov素晴らしい、ありがとう

@beikovに感謝し

@DavideDは今すぐ再テストできますか、 @ beikovはPRを更新したばかりです、それでも問題が解決するかどうか見てみましょう。

これらの問題を修正する必要があるPRは次のとおりです: hibernate / hibernate-orm#3664

確認済みですが、 hibernate-coreリリースが必要です。

#463で修正

皆さんありがとう

このページは役に立ちましたか?
0 / 5 - 0 評価