hibernate-reactive icon indicating copy to clipboard operation
hibernate-reactive copied to clipboard

BatchFetchSize.PADDED for collections with a dedicated collection table

Open yrodiere opened this issue 3 years ago • 6 comments

Apparently it's not currently implemented: https://github.com/hibernate/hibernate-reactive/blob/380a4e3888e8340042e552e4ad8ec1db232f21a1/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/collection/impl/ReactivePaddedBatchingCollectionInitializerBuilder.java#L35

If I set the batch fetch style to PADDED, the batch fetch size to 16, and I have a collection table somewhere, startup fails with this exception (on Quarkus):

java.lang.RuntimeException: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:538)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$8(ClassBasedTestDescriptor.java:368)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:368)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:192)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:78)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:136)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
        at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:188)
        at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:154)
        at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:128)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:428)
        at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
        at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:562)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:548)
Caused by: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:724)
        at io.quarkus.runtime.Application.start(Application.java:101)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at io.quarkus.runner.bootstrap.StartupActionImpl.run(StartupActionImpl.java:175)
        at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:494)
        ... 40 more
Caused by: javax.persistence.PersistenceException: Unable to build EntityManagerFactory
        at io.quarkus.hibernate.reactive.runtime.FastBootHibernateReactivePersistenceProvider.createEntityManagerFactory(FastBootHibernateReactivePersistenceProvider.java:93)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:80)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
        at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:118)
        at io.quarkus.hibernate.orm.runtime.JPAConfig.startAll(JPAConfig.java:42)
        at io.quarkus.hibernate.orm.runtime.HibernateOrmRecorder.startAllPersistenceUnits(HibernateOrmRecorder.java:88)
        at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits951856026.deploy_0(HibernateOrmProcessor$startPersistenceUnits951856026.zig:74)
        at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits951856026.deploy(HibernateOrmProcessor$startPersistenceUnits951856026.zig:40)
        at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:611)
        ... 47 more
Caused by: java.lang.UnsupportedOperationException
        at org.hibernate.reactive.loader.collection.impl.ReactivePaddedBatchingCollectionInitializerBuilder.createRealBatchingCollectionInitializer(ReactivePaddedBatchingCollectionInitializerBuilder.java:35)
        at org.hibernate.reactive.loader.collection.impl.ReactiveBatchingCollectionInitializerBuilder.createBatchingCollectionInitializer(ReactiveBatchingCollectionInitializerBuilder.java:62)
        at org.hibernate.reactive.persister.collection.impl.ReactiveBasicCollectionPersister.createCollectionInitializer(ReactiveBasicCollectionPersister.java:60)
        at org.hibernate.reactive.persister.collection.impl.ReactiveBasicCollectionPersister.createCollectionInitializer(ReactiveBasicCollectionPersister.java:40)
        at org.hibernate.persister.collection.AbstractCollectionPersister.postInstantiate(AbstractCollectionPersister.java:686)
        at java.base/java.util.concurrent.ConcurrentHashMap$ValuesView.forEach(ConcurrentHashMap.java:4772)
        at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:260)
        at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:303)
        at org.hibernate.reactive.session.impl.ReactiveSessionFactoryImpl.<init>(ReactiveSessionFactoryImpl.java:33)
        at io.quarkus.hibernate.reactive.runtime.boot.FastBootReactiveEntityManagerFactoryBuilder.build(FastBootReactiveEntityManagerFactoryBuilder.java:34)
        at io.quarkus.hibernate.reactive.runtime.FastBootHibernateReactivePersistenceProvider.createEntityManagerFactory(FastBootHibernateReactivePersistenceProvider.java:83)
        ... 55 more

(Note I executed this on a patched version of Quarkus, but the bug is there regardless of my patch)

yrodiere avatar May 03 '21 07:05 yrodiere

Note this is preventing us from enabling batch fetching by default for Hibernate Reactive in Quarkus; I ended up enabling it by default for Hibernate ORM only: https://github.com/quarkusio/quarkus/pull/16926

yrodiere avatar May 03 '21 07:05 yrodiere

It's working for other cases, right? (Many-to-one, one-to-many.)

gavinking avatar May 03 '21 08:05 gavinking

Note: #443 is a related issue.

gavinking avatar May 03 '21 08:05 gavinking

From the comments, it seems this code path is taken when an association has a dedicated collection table.

In my case it was a one-to-many, but without a mappedBy, so it may have had a dedicated collection table (I don't remember how those are mapped exactly).

No idea about one-to-one.

yrodiere avatar May 03 '21 08:05 yrodiere

Yep, I believe they result in an association table.

This isn't a huge surprise, since I implemented the batch fetch stuff before we had many-to-many support. So I think it just slipped through the cracks.

gavinking avatar May 03 '21 08:05 gavinking

@gavinking, I'm looking for a new task. Should I look into this one, or possibly https://github.com/hibernate/hibernate-reactive/issues/443?

gbadner avatar May 05 '21 17:05 gbadner