Hibernate-reactive: 示例失败,ORM 5.4.24

创建于 2020-11-20  ·  37评论  ·  资料来源: hibernate/hibernate-reactive

使用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)

所有37条评论

Goops,你是对的: @Sanne和我都因为 CI 中的其他虚假失败而错过了这一点。

我猜测这与#443有关。

该问题是否与 DirtyChecking 有关?
我认为这个问题与此有关: https :

无论如何,它发生在更新到 ORM 5.4.24 之后

该问题是否与 DirtyChecking 有关?

好吧,我认为该错误与批量加载有关。 不过我可能是错的。

该问题是否与 DirtyChecking 有关?

好吧,我认为该错误与批量加载有关。 不过我可能是错的。

哦,看来我错了,问题确实出在其他地方。

我正在处理一个测试用例。 希望我能尽快确认这一点。

但这是有道理的,因为只有示例失败,并且它是我们启用字节码增强的唯一地方

太好了。

所以,是的。 问题是启用字节码增强时对集合的脏检查。 我不知道为什么它以前有效。 可能, 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所以你认为这里发生的事情只是我们没有透明的惰性初始化(即它缺少对fetch()的调用),还是更深层次的东西?

@DavideD我在https://github.com/hibernate/hibernate-orm/pull/3645上发表了评论,因为对size()调用对我来说不合适。 (但我很容易错过一些东西。)

@DavideD所以你认为这里发生的事情只是我们没有透明的惰性初始化(即它缺少对 fetch() 的调用),还是更深层次的东西?

我认为这就是问题所在。 我想看看我是否可以在某个地方获取集合,以便它已经被获取。
顺便说一句,如果我为 EAGER 获取设置关联,一切都会正常。

我想看看我是否可以在某个地方获取集合,以便它已经被获取。

好的,但是不要_现在_就自杀,因为我仍然觉得我们正在获取与mappedBy未获取的关联只是为了检查其元素是错误的。 让我们看看@beikov@Sanne怎么说。

(OTOH,即使核心没有做正确的事情_在这种特殊情况下_,我们仍然可能需要修复您在其他情况下的工作。)

谢谢@gavinking

为什么电影收藏!= null ? 我试图在核心中重现这个,但不能,因为如果懒惰,这样的集合永远不应该是非空的。

嗯,我记得在某个地方有过一段很长的讨论。 我打开了一个问题,我认为这种“双重懒惰”或集合在 Hibernate ORM 中至少可以说是糟糕的,而对于 HR 来说,这是一个更糟糕的问题,其中获取不透明。 我们需要让您获得对集合的引用以对其调用fetch()

好的找到了。 那么这可能与#374有关吗?

collectionsInDefaultFetchGroupEnabled在 RX 中总是正确的吗?

嗯,如果我将它设置为 true,则集合会急切地初始化。

collectionsInDefaultFetchGroupEnabled在 RX 中总是正确的吗?

是的,是的。

嗯,如果我将它设置为 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 等级

相关问题

gavinking picture gavinking  ·  23评论

pqab picture pqab  ·  21评论

blafond picture blafond  ·  7评论

gavinking picture gavinking  ·  16评论

markusdlugi picture markusdlugi  ·  30评论