我有一个流程需要构建一个PDF文档,并将其与正在创建的其他100个文档相结合。
我想要多个线程。在我向服务传递的事件列表中,我需要生成并保存到数据库的PDF。文档也保存为目标,路径将保存到DB。
所以我使用的是10个线程的GPars。我遇到了一个问题,当我懒得取消事件时,我得到一条错误信息
未能懒惰地初始化角色集合: 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 )
我看到的结果是,当发生此错误时,之前已处理事件的内容将提交给数据库,这是一个问题。
我的最终目标是传递给方法的事件列表作为单个批处理完成,如果1失败,则没有记录提交给DB。
答案 0 :(得分:1)
从技术上讲,collectParallel()
旨在与无副作用的代码一起使用。但你可能仍然可以谨慎使用它。
假设buildDepositNotice(Event)
返回已保存的域实例,当该实例在Event.withNewSession(Closure)
闭包之外使用时,它将分离。虽然实例是分离的,但您可以访问它的属性等,但要坚持它,您必须首先将它重新连接到当前会话。
要收集存款通知,请确保该实例是withNewSession()
关闭中评估的最后一个表达式。
Event.withNewSession{ session ->
def depositNotice = buildDepositNotice(event)
session.flush()
depositNotice
}
如果pdfUtilService.concatPDFs()
需要保留存款通知,请确保首先在存款通知上调用attach()
。