Java 在Spring的并行流中使用JPA对象

Java 在Spring的并行流中使用JPA对象,java,spring,hibernate,jpa,java-stream,Java,Spring,Hibernate,Jpa,Java Stream,我正在用JPA开发SpringBoot应用程序。在代码中,我发现了一个非常可疑的部分,它的作用类似于(简化的示例,代码中包含大量杂乱的内容): 似乎并行导致了很多问题,包括以下错误: jvm 1 | org.hibernate.AssertionFailure: bug adding collection twice jvm 1 | at org.hibernate.engine.internal.StatefulPersistenceContext.addCollecti

我正在用JPA开发SpringBoot应用程序。在代码中,我发现了一个非常可疑的部分,它的作用类似于(简化的示例,代码中包含大量杂乱的内容):

似乎并行导致了很多问题,包括以下错误:

jvm 1    | org.hibernate.AssertionFailure: bug adding collection twice
jvm 1    |      at org.hibernate.engine.internal.StatefulPersistenceContext.addCollection(StatefulPersistenceContext.java:857)
jvm 1    |      at org.hibernate.engine.internal.StatefulPersistenceContext.addInitializedCollection(StatefulPersistenceContext.java:896)
jvm 1    |      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:242)
jvm 1    |      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221)
jvm 1    |      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194)
jvm 1    |      at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154)
jvm 1    |      at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249)
jvm 1    |      at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:212)
jvm 1    |      at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:133)
jvm 1    |      at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
jvm 1    |      at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
jvm 1    |      at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:88)
jvm 1    |      at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:688)
jvm 1    |      at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:75)
jvm 1    |      at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1991)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:570)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:252)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:566)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:739)
jvm 1    |      at org.hibernate.engine.internal.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:924)
jvm 1    |      at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:149)
jvm 1    |      at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
jvm 1    |      at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:88)
jvm 1    |      at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:688)
jvm 1    |      at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:75)
jvm 1    |      at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1991)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:570)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:252)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:566)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:135)
jvm 1    |      at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:277)
jvm 1    |      at java.util.Spliterators$IteratorSpliterator.estimateSize(Spliterators.java:1821)
jvm 1    |      at java.util.Spliterator.getExactSizeIfKnown(Spliterator.java:408)
jvm 1    |      at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:497)
jvm 1    |      at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
jvm 1    |      at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
jvm 1    |      at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
jvm 1    |      at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
jvm 1    |      at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
...
我想说,至少在
并行流中做一些与DB相关的事情是可疑的,但我无法找到任何证据表明应该避免这样做


如果您能帮助我解释错误或找到确凿的证据证明内部带有JPA的并行流是不安全的,我将不胜感激。

EntityManager
是线程绑定的。。。parallel使用多个线程,但对象仍然绑定到第一个
EntityManager
(那些讨厌的代理),现在当您尝试将其持久化到另一个线程时,您会突然在由多个
EntityManager维护的内容上出错。
。@M.Deinum:我觉得您是对的,但我很想详细了解这一点。您是说在一个线程中加载的实体在其他线程中使用通常是不安全的(即使它只有急切的集合)?如果是这样的话,您是否介意解释到底发生了什么,以便实体与两个实体管理者“紧密联系”?这真的很有趣,我很想理解。任何指向解释这一点的文档的指针都将不胜感激。也请随意添加此作为答案,以便我可以接受。谢谢!代码太少,无法具体说明,但您有一个服务,这就是查询,所以我假设这是使用JPA存储库来实现的。这将打开一个新的实体管理器,您可能会使用传入的实体作为查询参数(两个实体之间甚至可能存在关系)。@M.Deinum您应该将注释转换为答案
jvm 1    | org.hibernate.AssertionFailure: bug adding collection twice
jvm 1    |      at org.hibernate.engine.internal.StatefulPersistenceContext.addCollection(StatefulPersistenceContext.java:857)
jvm 1    |      at org.hibernate.engine.internal.StatefulPersistenceContext.addInitializedCollection(StatefulPersistenceContext.java:896)
jvm 1    |      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:242)
jvm 1    |      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221)
jvm 1    |      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194)
jvm 1    |      at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154)
jvm 1    |      at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249)
jvm 1    |      at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:212)
jvm 1    |      at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:133)
jvm 1    |      at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
jvm 1    |      at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
jvm 1    |      at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:88)
jvm 1    |      at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:688)
jvm 1    |      at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:75)
jvm 1    |      at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1991)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:570)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:252)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:566)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:739)
jvm 1    |      at org.hibernate.engine.internal.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:924)
jvm 1    |      at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:149)
jvm 1    |      at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
jvm 1    |      at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:88)
jvm 1    |      at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:688)
jvm 1    |      at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:75)
jvm 1    |      at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1991)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:570)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:252)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:566)
jvm 1    |      at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:135)
jvm 1    |      at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:277)
jvm 1    |      at java.util.Spliterators$IteratorSpliterator.estimateSize(Spliterators.java:1821)
jvm 1    |      at java.util.Spliterator.getExactSizeIfKnown(Spliterator.java:408)
jvm 1    |      at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:497)
jvm 1    |      at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
jvm 1    |      at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
jvm 1    |      at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
jvm 1    |      at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
jvm 1    |      at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
...