Exemplo de um dos 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)
Bolas, você está certo: @Sanne e eu perdemos isso por causa de outras falhas espúrias no IC.
Eu arrisco um palpite de que isso está relacionado a # 443.
Esse problema está relacionado ao DirtyChecking?
Acho que esse problema está relacionado a isso: https://github.com/hibernate/hibernate-reactive/issues/447
De qualquer forma, isso acontece após a atualização para ORM 5.4.24
Esse problema está relacionado ao DirtyChecking?
Bem, descobri que o bug está relacionado ao carregamento em lote. Eu posso estar errado embora.
Esse problema está relacionado ao DirtyChecking?
Bem, descobri que o bug está relacionado ao carregamento em lote. Eu posso estar errado embora.
Bem, parece que estou errado e o problema está realmente em outro lugar.
Estou trabalhando em um caso de teste. Espero poder confirmar isso em breve.
Mas faz sentido porque apenas o exemplo falha e é o único lugar onde ativamos os aprimoramentos de bytecode
OK ótimo.
Então sim. O problema é a verificação suja da coleção quando os aprimoramentos do código de byte estão habilitados. Não sei por que estava funcionando antes. Provavelmente, esse bug no ORM estava escondendo o problema e agora que foi corrigido, nós o vemos.
Uff, que PITA.
OTOH, por que a verificação suja da coleção ainda _material_ quando ainda não temos CollectionPersister
s?
Este é o problema:
O método aprimorado $$_hibernate_hasDirtyAttributes
mudou, 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;
}
a chamada para this.movies.size()
causa um LazyInitializationException
movies
é o nome da associação dentro do teste que criei
@DavideD, então você acha que o que está acontecendo aqui é apenas que não temos init preguiçoso transparente (ou seja, está faltando uma chamada para fetch()
), ou é algo mais profundo?
@DavideD Comentei em https://github.com/hibernate/hibernate-orm/pull/3645 , porque aquela ligação para size()
não parece certa para mim. (Mas eu poderia facilmente estar faltando alguma coisa.)
@DavideD, então você acha que o que está acontecendo aqui é apenas que não temos init preguiçoso transparente (ou seja, está faltando uma chamada para fetch ()), ou é algo mais profundo?
Acho que esse é o problema. Estou tentando ver se consigo buscar a coleção em algum lugar para que ela já seja buscada.
A propósito, tudo funciona se eu definir a associação para a busca EAGER.
Estou tentando ver se consigo buscar a coleção em algum lugar para que ela já seja buscada.
OK, mas não se mate nisso _ agora_ porque ainda parece errado para mim que estamos buscando uma associação não buscada com mappedBy
apenas para verificar seus elementos. Vamos ver o que @beikov e @Sanne têm a dizer.
(OTOH, mesmo que o core não esteja fazendo a coisa certa _neste caso em particular_, ainda podemos precisar da correção que você está trabalhando em outros casos.)
Para obter informações adicionais, este é o branch com o caso de teste (ainda um trabalho em andamento): https://github.com/DavideD/hibernate-reactive/tree/447-dirtychecking
Obrigado @gavinking
Por que a coleção de filmes é != null
? Tentei reproduzir isso no núcleo, mas não consegui porque essa coleção nunca deve ser não nula se preguiçosa.
Bem, eu me lembro que houve uma longa discussão em algum lugar. Um problema que abri onde argumentei que essa "preguiça dupla" ou coleções eram pelo menos indiscutivelmente ruins no Hibernate ORM, e um problema muito pior para o RH, onde a busca não é transparente. Precisamos permitir que você obtenha uma referência para a coleção para chamar fetch()
nela.
OK, encontrei. Então, isso poderia estar relacionado ao # 374?
collectionsInDefaultFetchGroupEnabled
sempre verdadeiro em RX?
Hmm, se eu definir como verdadeiro, a coleção é inicializada avidamente.
collectionsInDefaultFetchGroupEnabled
sempre verdadeiro em RX?
Sim, é.
Hmm, se eu definir como verdadeiro, a coleção é inicializada avidamente.
Ummmm ... sério? Essa não foi a intenção!
collectionsInDefaultFetchGroupEnabled
deve apenas incluir o proxy de coleção no grupo de busca padrão. Ele não deve realmente buscar a coleção em si.
Ou eu estraguei tudo ou algo mudou desde que escrevi aquele código.
Estou com você que a abordagem atual para aprimoramento não é ideal e que o campo deve ser inicializado para uma coleção persistente, mas acho que o problema que você está tendo no RX pode ser causado por outra coisa. Quando defino o sinalizador como verdadeiro, vejo a coleção sendo inicializada por meio deste rastreamento:
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)
Portanto, $$_hibernate_removeDirtyFields()
está chamando size()
em uma coleção não inicializada. _Deveria ser?
Estou com você que a abordagem atual para aprimoramento não é ideal e que o campo deve ser inicializado para uma coleção persistente, mas acho que o problema que você está tendo no RX pode ser causado por outra coisa. Quando defino o sinalizador como verdadeiro, vejo a coleção sendo inicializada por meio deste rastreamento:
Provavelmente estou faltando alguma coisa, mas não é o mesmo problema?
Ele ainda está chamando size()
mas de um método diferente
Você está certo. Aparentemente, as coleções não são registradas como preguiçosas, o que causa esse problema. Estou investigando agora.
Aqui está um PR que deve corrigir esses problemas: https://github.com/hibernate/hibernate-orm/pull/3664
Obrigado @beikov , o teste parece funcionar usando esse branch
@beikov excelente, obrigado
Obrigado @beikov , o teste parece funcionar usando esse branch
@DavideD pode testar novamente agora, @beikov acabou de atualizar o PR, vamos ver se ainda resolve o problema.
Aqui está um PR que deve corrigir esses problemas: hibernate / hibernate-orm # 3664
Confirmado, só precisamos da liberação de hibernate-core
.
Corrigido por # 463
Obrigado a todos