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

时间:2017-05-17 16:04:44

标签: java spring hibernate jpa java-stream

我正在使用JPA进行spring-boot应用程序。在代码中我发现了一个非常可疑的部分,它做了类似的事情(简化示例,代码中包含很多混乱):

entityRepository.findAll().parallel() // The findAll returns already a stream, it's a CrudRepository from Spring
   .filter (...)
   .map(e -> {
      OtherDbObject other = service.getOtherDbObjectBasedOn(e);
      boolean hasSomething = other.getProperties().stream() //properties is fetch type EAGER @OneToMany collection in OtherDbObject
        .filter(...)
        .findFirst()
        .isPresent();

      ...
   })

parallel似乎造成了很多麻烦,包括:

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)
...

我会说在parallel流中做一些与数据库相关的事情至少是可疑的,但我无法证明应该避免这种情况。

我很感激任何帮助,无论是解释错误还是找到可靠的证据证明内部JPA的并行流是不安全的。

0 个答案:

没有答案