处理大型域对象列表的最佳方法是什么?

时间:2013-09-17 11:00:14

标签: grails gorm

处理大型域对象列表的最佳方法是什么? 例如,我有“用户”和“预订”域,并且对Book对象有权限READ。 当我添加新书时,我想为本书的所有用户设置READ权限。 起初是一个代码:

def users = Users.findAll{ ... }
users.each { addPermission(book, it, READ) }  

我正在使用Spring Security Core和ACL插件。 但现在,我认为这不是将10000个用户对象加载到内存的最佳方式。 我将使用来自Criteria的maxResults(???)的SCROLL方法。 所以我的问题是最好的方法是什么?如何确定MaxResults的最佳数量?

3 个答案:

答案 0 :(得分:2)

对于这样的事情,我会进行批量更新。 ExecuteUpdate允许您执行此类操作,并且其性能更高。查看此示例并根据您的需要进行自定义。

def updatedRecords = User.executeUpdate("update User set permission = 'READ' where somecriteriaOrNot ")

答案 1 :(得分:1)

Grails的更多方法是使用批处理。试试下面给出的例子: 编辑:改进了答案。现在,使用基于分页的批处理。

             def noOfObjectsTobeProcessedAtAtime=1000//Step or pagination size...

    List offsetMaxMapList = (0..User.count()-1).step(noOfObjectsTobeProcessedAtAtime).collect{[max:noOfObjectsTobeProcessedAtAtime,offset:it]}
    offsetMaxMapList.each{offsetMaxMap->
        addPermissionToUserInBatch(params)  

    }

    def addPermissionToUserInBatch(params){
        def batch = []
                def session
                def users = Users.createCriteria().list(params){}

                users.eachWithIndex { user, index ->
                    batch << user

                    if (batch.size() >= batchSize) {
                        User.withTransaction {
                            batch.each {User userObject ->
                             addPermission(book, userObject, READ)
                                }
                        }
                        batch.clear()

                    } else if (batch.size() < batchSize && (users.size() - index - 1) == 0) {
                        User.withTransaction {
                            batch.each {User userObject ->
                                 addPermission(book, userObject, READ)
                                }
                        }
                        batch.clear()
                    }
                    session = sessionFactory.getCurrentSession()
                    session.clear()
                }

    }

希望有所帮助!!!

答案 2 :(得分:0)

谢谢大家。我想总结一下。我希望我能成为一个模板。

def dc = new DetachedCriteria(Users).build{
    //some conditions of criteria 
}
def count = dc.count()

// Optional:            
// dc = dc.build{
//     projections { property('username') }
// }

def batchSize = 50 // Hibernate Doc recommends 10..50
0.step(count, batchSize){ offset-> 
    dc.list(offset:offset, max:batchSize).each{
       // doSmthWithTransaction(it)
    }
    //clear the first-level cache
    //def hiberSession = sessionFactory.getCurrentSession() 
    //hiberSession.clear()
    // or
    Users.withSession { session -> session.clear() }
}

P.S。我在这里不使用Transaction,因为我在doSmthWithTransaction方法

上使用它