我相信这很容易,但在文档或谷歌中找不到任何示例。
假设我们有客户和帐户域对象,因此:
Class Customer {
String name
}
Class Account {
Customer customer
BigDecimal balance
Currency currency
}
如果我不使用grails,并且没有ORM,我会在原始SQL中做这样的事情:
Select c.name, a.balance
from customer c, account a
where name like xxx
and a.customer_id = c.id
甚至:
Select c.*, a.balance, a.currency_id
from customer c, account a
where name like xxx
and a.customer_id = c.id
甚至:
Select c.*, a.balance, cur.iso
from customer c, account a, currency cur
where name like xxx
and a.customer_id = c.id
and cur.id = a.currency_id
但是,在圣杯中,我正在寻找一种方法来返回一组已加载帐户的客户。 这样我就可以将 Customer 对象传递回视图,而不是字符串列表。
这必须作为单个查询完成,而不是作为一个查询来获取所有客户,然后为每个客户查询以获取他们的余额(可能有数百万个客户(
我知道 grails 会延迟加载,如果我想,我可以在每次查询玩家时强制 grails 加载帐户,但这会影响我想查找客户但不需要余额的时间。
我也知道我可以在 grails 中硬编码 SQL/HQL,并将结果作为字符串返回以供 gsp 页面呈现,但这不太像 grails。
此外,我不想在播放器中添加指向许多帐户的链接,因为这可能会对性能产生严重影响,并且不是通用解决方案(我有大约 400 个域对象,其中许多对象需要一个联接查询解决方案(。
请注意,此示例假设每个玩家都有一个帐户。如果这不是真的,如果我通过 SQL 执行此操作,我将使用外部连接。不知道 GORM 中的等价物是什么。
有什么建议吗?
更新答案,因为我没有正确阅读。
首先,您提到在视图中执行gorm
或HQL
查询。也许有一天你会感谢我,但你真的应该尝试保持演示作为演示。当你试图做发现或复杂的决策时,是时候退后一步,思考概念是否需要重新思考,或者如果不可能,如何将这个逻辑实现到一个要么工作,要么依赖服务来完成工作的taglib
。
到目前为止,您需要的最简单答案是修改 Customer 类并执行自定义 Set/Let 来抓取属于其他对象的对象:
Class Customer {
String name
Set<Account> getAccounts() {
return (Account?.findAll{customer==this} as Set<Account>)
/// Or write hql you can also add things like take to limit it
//return Account?.findAllByCustomer(this)?.take(5)
}
Account getAccount() {
return Account?.find{customer==this}
}
}
然后,当您遍历所有用户时
<g:each in ="${instance.customers}" var="customer">
${u.name} vs ${customer?.account?.balance} ${customer?.accounts?.balance}
</g:each>
只有当你击中每个用户时,才会调用 getter
或者尝试将其全部编写为一个查询,该查询获取所有内容,该查询可能在查询中或查询外部进行分组,但是它起作用并传入偏移量和最大值,然后将其列出,以便然后使用分页来控制如此多的记录,HQL 查询的基础知识将是这样的(因为您希望所有用户可能有也可能没有余额,而客户没有与客户有关系(
String query= """Select new map(c.name as name, a.balance as balance)
from Customer c, Account a
where name like :name
and a.customer.id = c.id
"""
Map mp=[:]
name='%'+params.name+'%'
def result=Account.executeQuery(query,mp,[readOnly:true])