Hibernate-reactive: Beispiel schlägt fehl mit ORM 5.4.24

Erstellt am 20. Nov. 2020  ·  37Kommentare  ·  Quelle: hibernate/hibernate-reactive

Beispiel für eines der Protokolle mit org.hibernate:hibernate-core:5.5.0-SNAPSHOT:20201117.201048-196 :

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

Alle 37 Kommentare

Goops, du hast Recht: @Sanne und ich haben das beide wegen anderer falscher Fehler in der CI verpasst.

Ich gehe davon aus, dass dies mit #443 zusammenhängt.

Hängt das Problem mit DirtyChecking zusammen?
Ich denke, dieses Problem hängt damit zusammen: https://github.com/hibernate/hibernate-reactive/issues/447

Wie auch immer, es passiert nach dem Update auf ORM 5.4.24

Hängt das Problem mit DirtyChecking zusammen?

Nun, ich dachte mir, dass der Fehler mit dem Stapelladen zusammenhängt. Ich könnte mich aber irren.

Hängt das Problem mit DirtyChecking zusammen?

Nun, ich dachte mir, dass der Fehler mit dem Stapelladen zusammenhängt. Ich könnte mich aber irren.

Na ja, anscheinend liege ich falsch und das Problem liegt tatsächlich woanders.

Ich arbeite an einem Testfall. Hoffentlich kann ich dies bald genug bestätigen.

Es ist jedoch sinnvoll, da nur das Beispiel fehlschlägt und es der einzige Ort ist, an dem wir die Bytecode-Erweiterungen aktivieren

Okay, großartig.

Also ja. Das Problem ist die schmutzige Überprüfung der Sammlung, wenn Bytecode-Erweiterungen aktiviert sind. Ich weiß nicht, warum es vorher funktioniert hat. Wahrscheinlich hat dieser Fehler in ORM das Problem versteckt und jetzt, da es behoben ist, sehen wir es.

Uff, was für ein PITA.

OTOH, warum ist die Überprüfung der Sammlung selbst _wichtig_, wenn wir noch nicht einmal CollectionPersister s haben?

Dies ist das Problem:

Die erweiterte Methode $$_hibernate_hasDirtyAttributes hat sich geändert, von

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

zu

    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;
    }

der Aufruf von this.movies.size() verursacht ein LazyInitializationException

movies ist der Name der Assoziation in dem von mir erstellten Test

@DavideD also denkst du, was hier vor sich geht, ist nur, dass wir keine transparente lazy init haben (dh es fehlt ein Aufruf an fetch() ), oder ist es etwas tiefer?

@DavideD Ich habe https://github.com/hibernate/hibernate-orm/pull/3645 kommentiert, weil dieser Aufruf an size() mich nicht richtig aussieht. (Aber ich könnte leicht etwas übersehen.)

@DavideD Also denkst du, was hier vor sich geht, ist, dass wir keine transparente faule Init haben (dh es fehlt ein Aufruf von fetch()), oder ist es etwas tiefer?

Ich denke, das ist das Problem. Ich versuche zu sehen, ob ich die Sammlung irgendwo holen kann, damit sie bereits geholt wird.
Übrigens funktioniert alles, wenn ich die Assoziation für EAGER-Abrufen setze.

Ich versuche zu sehen, ob ich die Sammlung irgendwo holen kann, damit sie bereits geholt wird.

OK, aber bringen Sie sich _jetzt_ nicht um, weil es sich für mich immer noch falsch anfühlt, dass wir eine nicht geholte Assoziation mit mappedBy abrufen, nur um deren Elemente zu überprüfen. Mal sehen, was @beikov und @Sanne zu sagen haben.

(OTOH, selbst wenn der Kern _in diesem speziellen Fall_ nicht das Richtige tut, brauchen wir in anderen Fällen möglicherweise noch die Korrektur, an der Sie arbeiten.)

Danke @gavinking

Warum ist die Filmsammlung != null ? Ich habe versucht, dies im Kern zu reproduzieren, konnte es aber nicht, da eine solche Sammlung niemals ungleich null sein sollte, wenn sie faul ist.

Ich erinnere mich, dass es irgendwo eine lange Diskussion gab. Ein Thema, das ich eröffnet habe, in dem ich argumentierte, dass diese "Doppelfaulheit" oder Sammlungen im Hibernate ORM zumindest wohl schlecht waren und ein viel schlimmeres Problem für die Personalabteilung, bei dem das Abrufen nicht transparent ist. Wir müssen Ihnen erlauben, eine Referenz auf die Sammlung zu erhalten, um fetch() darauf aufzurufen.

Okay habe es gefunden. Könnte das also mit #374 zusammenhängen?

Ist collectionsInDefaultFetchGroupEnabled in RX immer wahr?

Hmm, wenn ich es auf true setze, wird die Sammlung eifrig initialisiert.

Ist collectionsInDefaultFetchGroupEnabled in RX immer wahr?

Ja, das ist es.

Hmm, wenn ich es auf true setze, wird die Sammlung eifrig initialisiert.

Ähm... wirklich? Das war nicht die Absicht!

collectionsInDefaultFetchGroupEnabled soll nur den Sammlungs- Proxy in die Standard-Abrufgruppe aufnehmen. Es soll nicht die Sammlung selbst holen .

Entweder habe ich es total vermasselt, oder etwas hat sich geändert, seit ich diesen Code geschrieben habe.

Ich stimme Ihnen zu, dass der derzeitige Ansatz zur Verbesserung nicht ideal ist und dass das Feld mit einer persistenten Sammlung initialisiert werden sollte, aber ich denke, dass das Problem, das Sie in RX haben, durch etwas anderes verursacht werden könnte. Wenn ich das Flag auf true setze, sehe ich, dass die Sammlung durch diese Ablaufverfolgung initialisiert wird:

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() ruft also size() für eine nicht initialisierte Sammlung auf. _Sollte es sein?

Ich stimme Ihnen zu, dass der derzeitige Ansatz zur Verbesserung nicht ideal ist und dass das Feld mit einer persistenten Sammlung initialisiert werden sollte, aber ich denke, dass das Problem, das Sie in RX haben, durch etwas anderes verursacht werden könnte. Wenn ich das Flag auf true setze, sehe ich, dass die Sammlung durch diese Ablaufverfolgung initialisiert wird:

Ich übersehe wahrscheinlich etwas, aber ist das nicht das gleiche Problem?
Es ruft immer noch size() aber von einer anderen Methode

Du hast recht. Anscheinend sind die Sammlungen nicht als faul registriert, was dieses Problem verursacht. Ich recherchiere jetzt.

Hier eine PR, die diese Probleme beheben sollte: https://github.com/hibernate/hibernate-orm/pull/3664

Danke @beikov , der Test scheint mit diesem Zweig zu funktionieren

@beikov ausgezeichnet, danke

Danke @beikov , der Test scheint mit diesem Zweig zu funktionieren

@DavideD können Sie jetzt erneut testen , behoben wird .

Hier ein PR, der diese Probleme beheben sollte: hibernate/hibernate-orm#3664

Bestätigt, wir brauchen nur eine Freigabe von hibernate-core .

Behoben von #463

Danke an alle

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen