GPars,GORM,批量上传

时间:2015-10-22 20:04:04

标签: multithreading grails gorm gpars

我有一个流程需要构建一个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。

1 个答案:

答案 0 :(得分:1)

从技术上讲,collectParallel()旨在与无副作用的代码一起使用。但你可能仍然可以谨慎使用它。

假设buildDepositNotice(Event)返回已保存的域实例,当该实例在Event.withNewSession(Closure)闭包之外使用时,它将分离。虽然实例是分离的,但您可以访问它的属性等,但要坚持它,您必须首先将它重新连接到当前会话。

要收集存款通知,请确保该实例是withNewSession()关闭中评估的最后一个表达式。

Event.withNewSession{ session ->
    def depositNotice = buildDepositNotice(event)

    session.flush()
    depositNotice
} 

如果pdfUtilService.concatPDFs()需要保留存款通知,请确保首先在存款通知上调用attach()