只要没有超过 10.000 个对象的批次,GORM 开箱即用。如果没有优化,您将面临 outOfMemory 问题。
常见的解决方案是刷新()和清除() session 每个 n(例如n = 500)个对象:
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
关于performance - Grails hibernate session 批量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13748764/