3

处理大量域对象的最佳方法是什么?例如,我有 'Users' 和 'Book' 域,并且 Book 对象有 READ 权限。当我添加一本新书时,我想为这本书的所有用户设置阅读权限。起初是一个代码:

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

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

4

3 回答 3

2

对于这样的事情,我会进行批量更新。ExecuteUpdate 允许你做这样的事情,而且它的性能要高得多。查看此示例并根据您的需要对其进行自定义。

def updatedRecords = User.executeUpdate("update User set permission = 'READ' where somecriteriaOrNot ")
于 2013-09-17T11:44:08.560 回答
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()
                }

    }

希望有帮助!!!

于 2013-09-17T13:35:43.953 回答
0

谢谢你们。我想总结一下。我希望 ti 将成为我的模板。

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() }
}

PS 我在这里不使用 Transaction 因为我在 doSmthWithTransaction 方法上使用它

于 2013-09-18T06:57:26.987 回答