Hibernate-reactive: El ejemplo falla con ORM 5.4.24

Creado en 20 nov. 2020  ·  37Comentarios  ·  Fuente: hibernate/hibernate-reactive

Ejemplo de uno de los registros usando 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

Todos 37 comentarios

Vaya, tienes razón: @Sanne y yo nos perdimos esto debido a otras fallas

Me arriesgo a adivinar que esto está relacionado con el # 443.

¿Ese problema está relacionado con DirtyChecking?
Creo que ese problema está relacionado con esto: https://github.com/hibernate/hibernate-reactive/issues/447

De todos modos, sucede después de la actualización a ORM 5.4.24

¿Ese problema está relacionado con DirtyChecking?

Bueno, pensé que el error está relacionado con la carga por lotes. Aunque podría estar equivocado.

¿Ese problema está relacionado con DirtyChecking?

Bueno, pensé que el error está relacionado con la carga por lotes. Aunque podría estar equivocado.

Bueno, parece que estoy equivocado y el problema está en otra parte.

Estoy trabajando en un caso de prueba. Espero poder confirmar esto lo suficientemente pronto.

Sin embargo, tiene sentido porque solo falla el ejemplo y es el único lugar donde habilitamos las mejoras del código de bytes

Vale genial.

Entonces sí. El problema es la verificación sucia de la colección cuando se habilitan las mejoras del código de bytes. No sé por qué funcionaba antes. Probablemente, este error en ORM estaba ocultando el problema y ahora que está solucionado lo vemos.

Uff, que PITA.

OTOH, ¿por qué la recopilación se ensucia con la verificación incluso _materia_ cuando ni siquiera tenemos CollectionPersister s todavía?

Este es el problema:

El método mejorado $$_hibernate_hasDirtyAttributes ha cambiado, de

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

para

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

la llamada a this.movies.size() provoca un LazyInitializationException

movies es el nombre de la asociación dentro de la prueba que he creado

@DavideD, entonces, ¿crees que lo que está sucediendo aquí es solo que no tenemos un inicio perezoso transparente (es decir, falta una llamada a fetch() ), o es algo más profundo?

@DavideD He comentado en https://github.com/hibernate/hibernate-orm/pull/3645 , porque esa llamada a size() no me parece correcta. (Pero fácilmente podría estar perdiendo algo).

@DavideD, entonces, ¿crees que lo que está sucediendo aquí es solo que no tenemos un inicio perezoso transparente (es decir, falta una llamada a fetch ()), o es algo más profundo?

Creo que ese es el problema. Estoy tratando de ver si puedo recuperar la colección en algún lugar para que ya esté recuperada.
Por cierto, todo funciona si configuro la asociación para la búsqueda EAGER.

Estoy tratando de ver si puedo recuperar la colección en algún lugar para que ya esté recuperada.

Está bien, pero no te mates con eso _ ahora mismo_ porque todavía me parece mal que estemos obteniendo una asociación no obtenida con mappedBy solo para verificar sus elementos. Veamos qué tienen que decir @beikov y @Sanne .

(OTOH, incluso si el núcleo no está haciendo lo correcto _en este caso en particular_, es posible que necesitemos corregirlo en otros casos).

Gracias @gavinking

¿Por qué la colección de películas es != null ? Traté de reproducir esto en el núcleo, pero no pude porque tal colección nunca debería ser no nula si es perezosa.

Bueno, recuerdo que hubo una larga discusión en alguna parte. Abrí un problema en el que sostenía que esta "doble pereza" o colecciones era al menos posiblemente mala en Hibernate ORM, y un problema mucho peor para RR.HH., donde la búsqueda no es transparente. Necesitamos permitirle obtener una referencia a la colección para llamar fetch() en ella.

OK lo encontré. Entonces, ¿podría esto estar relacionado con el n. ° 374?

¿ collectionsInDefaultFetchGroupEnabled siempre es cierto en RX?

Hmm, si lo configuro en verdadero, la colección se inicializa con entusiasmo.

¿ collectionsInDefaultFetchGroupEnabled siempre es cierto en RX?

Sí, lo es.

Hmm, si lo configuro en verdadero, la colección se inicializa con entusiasmo.

Ummmm ... ¿de verdad? ¡Esa no era la intención!

Se supone que collectionsInDefaultFetchGroupEnabled solo incluye el proxy de colección en el grupo de recuperación predeterminado. No se supone que vaya a buscar la colección en sí.

Entonces, o lo arruiné por completo, o algo ha cambiado desde que escribí ese código.

Estoy de acuerdo con usted en que el enfoque actual para la mejora no es ideal y que el campo debe inicializarse en una colección persistente, pero creo que el problema que está teniendo en RX podría deberse a otra cosa. Cuando configuro la bandera en verdadero, veo que la colección se inicializa a través de este seguimiento:

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)

Entonces $$_hibernate_removeDirtyFields() está llamando a size() en una colección no inicializada. _¿Deberia ser?

Estoy de acuerdo con usted en que el enfoque actual para la mejora no es ideal y que el campo debe inicializarse en una colección persistente, pero creo que el problema que está teniendo en RX podría deberse a otra cosa. Cuando configuro la bandera en verdadero, veo que la colección se inicializa a través de este seguimiento:

Probablemente me esté perdiendo algo, pero ¿no es este el mismo problema?
Sigue llamando a size() pero desde un método diferente

Tienes razón. Aparentemente, las colecciones no están registradas como perezosas, lo que causa este problema. Estoy investigando ahora.

Aquí un PR que debería solucionar estos problemas: https://github.com/hibernate/hibernate-orm/pull/3664

Gracias @beikov , la prueba parece funcionar usando esa rama

@beikov excelente, gracias

Gracias @beikov , la prueba parece funcionar usando esa rama

@DavideD puede volver a probar ahora,

Aquí un PR que debería solucionar estos problemas: hibernate / hibernate-orm # 3664

Confirmado, solo necesitamos una liberación de hibernate-core .

Corregido por # 463

Gracias a todos

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

arifpratama398 picture arifpratama398  ·  10Comentarios

yaakov-berkovitch picture yaakov-berkovitch  ·  16Comentarios

akoufa picture akoufa  ·  30Comentarios

gavinking picture gavinking  ·  23Comentarios

gavinking picture gavinking  ·  16Comentarios