Performance 成批执行Grails hibernate会话
只要批处理对象不超过10000个,GORM就可以在开箱即用的情况下正常工作。如果没有优化,您将面临outOfMemory问题 常见的解决方案是对每个n(例如n=500)对象刷新()和清除()会话: 但有些问题我无法解决:Performance 成批执行Grails hibernate会话,performance,hibernate,grails,gorm,Performance,Hibernate,Grails,Gorm,只要批处理对象不超过10000个,GORM就可以在开箱即用的情况下正常工作。如果没有优化,您将面临outOfMemory问题 常见的解决方案是对每个n(例如n=500)对象刷新()和清除()会话: 但有些问题我无法解决: 如果我使用currentSession,则控制器会失败,因为会话为空 如果我使用sessionFactory.openSession(),那么当前会话仍然在FooService中使用。当然,我可以使用session.save(object)符号。但这意味着,我必须修改fooSe
任何想法都是好的 我建议对这种批处理使用无状态会话。请参阅本文:修改后的方法是:
rawObjects
),并保存这些对象的所有ID的列表顺便说一下。但请注意,此链接中的代码不正确;清除会话的行应该在if语句中,就像您在解决方案中所做的一样。这看起来像是应该完全在服务方法中完成的工作。如果在维修方法中,您使用了
currentSession
,您的控制器是否仍然工作?我同意@doelleri的说法。服务业是实现这一目标的最佳场所。另外,请记住,默认情况下它们是事务性的,如果您想手动处理状态,请使用Domain.withTransaction
并设置static transactional=false
,或者让服务负责提交/回滚。我在那里发布的代码已经在服务方法中。是的,我可以使用服务方法的事务上下文,但它不能解决我的问题@doelleri-对你的问题的答案是:控制器会刹车,因此用户除了关闭浏览器外,在应用程序中不能做其他事情。(参见问题1)查看。很容易集成到grails中,非常强大,谢谢您的建议!我想避免使用Spring批处理,因为它很复杂。我已经集成了quarz作业,这意味着springbatch和quarz在一个应用程序中将有两种作业调度方法。有没有更简单的解决办法?
Session session = sessionFactory.currentSession
Transaction tx = session.beginTransaction();
def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
Date yesterday = new Date() - 1
Criteria c = session.createCriteria(Foo.class)
c.add(Restrictions.lt('lastUpdated',yesterday))
ScrollableResults rawObjects = c.scroll(ScrollMode.FORWARD_ONLY)
int count=0;
while ( rawObjects.next() ) {
def rawOject = rawObjects.get(0);
fooService.doSomething()
int batchSize = 500
if ( ++count % batchSize == 0 ) {
//flush a batch of updates and release memory:
try{
session.flush();
}catch(Exception e){
log.error(session)
log.error(" error: " + e.message)
throw e
}
session.clear();
propertyInstanceMap.get().clear()
}
}
session.flush()
session.clear()
tx.commit()