我有一个过程,需要构建一个PDF文档,并将其与正在创建的其他1000多个文档相结合。
我想要多个线程。将需要生成并保存到DB中的事件列表传递到服务中。文档也保存为目标,路径保存到DB。
所以我用的是GPars和10个线程。我遇到了一个问题,当我懒得取掉事件时,我会收到一条错误消息。
未能延迟初始化角色集合: com.srm.billing.DepositNotice.depositNoticeRevisions,未关闭会话或会话;嵌套异常为org.hibernate.LazyInitializationException:未能延迟初始化角色集合: com.srm.billing.DepositNotice.depositNoticeRevisions,没有关闭会话或会话
我注意到有几个站点说Hibernate不是线程安全的,这就是我认为是导致问题的原因。
GParsPool.withPool( poolSize ) { forkJoinPool ->
depositNotices = pEvents.collectParallel{ event ->
Event.withNewSession{ session ->
return buildDepositNotice( event )
session.flush()
}
}
}
byte[] findlDocument = null
finalDocument = pdfUtilService.concatPDFs( depositNotices )我看到的结果是,当此错误发生时,先前处理过的事件将提交给DB,这是一个问题。
我的最终目标是将传递给该方法的事件列表作为一个批处理完成,其中如果1失败,则不向DB提交任何记录。
发布于 2015-10-23 04:09:29
从技术上讲,collectParallel()是用来与副作用无关的代码一起使用的.但你还是可以谨慎地使用它。
假设buildDepositNotice(Event)返回一个保存的域实例,当该实例在Event.withNewSession(Closure)闭包之外使用时,它将被分离。当实例被分离时,您可以访问它的属性等等,但是要保持它,您必须首先将它重新附加到当前会话。
要收集押金通知,请确保实例是在withNewSession()闭包中计算的最后一个表达式。
Event.withNewSession{ session ->
def depositNotice = buildDepositNotice(event)
session.flush()
depositNotice
} 如果pdfUtilService.concatPDFs()需要持久化订金通知,那么确保它首先调用了订金通知上的attach()。
https://stackoverflow.com/questions/33289710
复制相似问题