Grails中的批更新记录

Grails中的批更新记录,grails,groovy,gorm,Grails,Groovy,Gorm,我必须根据单个操作计算每个用户的“总数”——也就是说,一个用户有许多操作,每个操作都有一个点。所以我需要得到所有动作的所有点的总和 动作会定期进行加减。因为这可能是一个相当繁重的操作,所以每次需要时执行“total”是不可行的。因此,我考虑每天为每个用户运行一次操作,并将用户的总分存储为int 因为我有成千上万的用户,我正试图找出最好的方法来做到这一点。我基本上应该遍历所有用户并每次调用User.save(),还是在Grails/GORM中有某种批更新机制可以使用?调用User.save()实际

我必须根据单个操作计算每个用户的“总数”——也就是说,一个用户有许多操作,每个操作都有一个点。所以我需要得到所有动作的所有点的总和

动作会定期进行加减。因为这可能是一个相当繁重的操作,所以每次需要时执行“total”是不可行的。因此,我考虑每天为每个用户运行一次操作,并将用户的总分存储为int

因为我有成千上万的用户,我正试图找出最好的方法来做到这一点。我基本上应该遍历所有用户并每次调用User.save(),还是在Grails/GORM中有某种批更新机制可以使用?

调用
User.save()
实际上不会将更改写入数据库,只有在刷新Hibernate会话时才会写入更改()

您可以通过访问
SessionFactory
并对生成的会话调用flush来手动刷新会话,如下所示

我想您可能希望使用批处理技术加载用户,以确保不会同时将数千个用户都放在内存中


另外,如果您希望缓存值,但每当您添加一个可以挂接到active record的事件中以更新计算值的操作时,就会自动更新该值,下面是一个

问题中的模型是您的实际模型还是它的简化版本?如果您所做的只是用户有许多操作,并且每个操作都有一个您想要总结的点值(一个整数?),那么这就是关系数据库擅长的事情。如果您的数据库上有适当的索引,我认为这将是一个非常快速的调用,只要您正在执行groupBy查询(或使用grails投影条件)

下面是一个示例方法,该方法将获取用户列表,并返回一个数组,该数组将user.id与用户当前拥有的点数配对:

def calculateCurrentPoints(users) {
    Action.executeQuery('select a.user.id, sum(points) from Action a where a.user.id in (:userIds) group by a.user.id', [userIds: users.id])
}
如果需要,您可以轻松地将其转换为用户id到点的映射,以便于查找:

def calculateCurrentPoints(users) {
    def result = Action.executeQuery('select a.user.id, sum(points) from Action a where a.user.id in (:userIds) group by a.user.id', [userIds: users.id])
    result.inject([:]) { map, userWithPoints -> 
        map[userWithPoints[0]] = userWithPoints[1]
        return map
    }
}

如果这真的比我想象的要慢,那么您可以使用类似于我上面介绍的带有HQL的executeUpdate来更新每个用户的“totalPoints”字段(或者在向该用户添加新操作时将其作为服务的一部分进行更新)

你的问题很有趣。如果我有时间,我会尽量正确回答你。你不需要总的数字总是准确的吗?为什么不在运行中计算一个用户的总数呢?Mike——这是我最初的做法,但它对性能有着非常重要的影响——特别是当我需要同时显示多个用户的总数时。在我的情况下,这是一个相当复杂的计算。