grails 一对多求和

Posted

技术标签:

【中文标题】grails 一对多求和【英文标题】:grails sum one-to-many 【发布时间】:2011-08-04 17:32:31 【问题描述】:

在我认为非常琐碎的事情上,我需要帮助。

class User 
    String name 
    static hasMany = [files : File]


class File 
    long size

现在,当我需要给定用户拥有的所有文件的总大小时,我会使用以下方法:

def user = User.get(id)
user.files.each(total+=it.size)

但它有多难看,当我确信它可以通过简单的 SQL 或 GORM/CRITERIA 的简单选择和查询来完成时

我尝试过类似 File.sumBySize..()

或者

def c = File.createCriteria()
def f = c.list
    eq("user",  user)   // What here ?
    projections
        
        sum("size")
        
       

我不知道如何指定未在 File 类中但在 Grails 连接表中定义的父(用户)关系

任何帮助表示赞赏

【问题讨论】:

为什么这么丑?我只是将该代码放在用户域中的便捷方法中。然后只需调用 userInstance.totalFileSize() 我不知道。我只是觉得这应该通过查询而不是循环收集来完成。我也很好奇如何以其他方式进行这项工作。我没有按标准做到这一点.. :( 【参考方案1】:

为什么这么丑?只需要 1 条语句(根本没有 SQL)来总结所有文件大小。虽然如果你愿意,也许可以像这样使用 HQL:

def user = User.get(id)
def sum = File.executeQuery("select sum(f.size) from File f where f.user = ?", user);

但我认为您需要向 File 添加一个 belongsTo 才能做到这一点。可能有一个更简单的 HQL/GORM 方法,但目前我还没有想到,但老实说,我认为没有比你已经做过的更简单的方法了。

【讨论】:

是的,这仅在我添加 belongsTo = [user: User] 时有效。谢谢【参考方案2】:

您可以使用 HQL 查询来做到这一点,但是“大小”字段的名称存在一个小问题 (似乎是保留字)。如果您将其重命名为“length”、“fileSize”等,那么这将起作用:

User.executeQuery(
   'select sum(file.length) from User u join u.files file where u.id=:userId',
   [userId: id])[0]

【讨论】:

...但这似乎比您的原始代码更复杂,哈哈。 ..我知道是对的 :D 但我只是想看看其他选择。此外.. Gorm->hibernate-> 背后到底发生了什么?最后还是sql吧?我想知道是什么提供了更好的性能,在 DB 之上的操作更少等等。 对于这个有点做作的例子,按照原来的方式来做不会那么糟糕。但在实际应用中,File 类很可能还有其他字段,因此直接查询只获取您需要的数据会更有效。【参考方案3】:

在 Groovy 代码中求和文件大小的更优雅的方法是:

def total = user.files.sum it.size

但是,如果您可以在返回用户的查询中计算文件大小总计,那么我会这样做。

【讨论】:

以上是关于grails 一对多求和的主要内容,如果未能解决你的问题,请参考以下文章

Grails 3 中一对多域的深拷贝

在 Grails 中,需要为一对多关系定义一个 Set 吗?

为啥当我在 grails 上删除一对多关系上的父级时,会在子级上调用 beforeInsert 事件?

在 Grails 中扩展具有一对多关系的域类

与一对多 Spring Data JPA 求和

grails一对一关联关系