只要不存在超过10.000个对象的批次,GORM便可以很好地使用。没有优化,您将面临outOfMemory问题。
常见的解决方案是对每个n(例如n = 500)个对象进行flush()和clear() session :
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()
但是有一些我无法解决的问题:
因此,我不知道如何在不使FooService.doSomething()更复杂的情况下解决问题。我正在寻找适用于所有域的withSession {}之类的东西。或者在开始时保存 session ( session tmp = currentSession),然后执行类似sessionFactory.setCurrentSession(tmp)的操作。两者都不存在!
任何想法都是好主意!
最佳答案
我建议对这种批处理使用无状态 session 。看到这个帖子:Using StatelessSession for Batch processing