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 中,需要为一对多关系定义一个 Set 吗?