我确信这很容易,但无法在documentation或Google中找到任何相关示例。
假设我们有客户和帐户域对象:
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
但是在grails中,我正在寻找一种方法来返回已经加载帐户的一组客户。这样我就可以将Customer对象传递回视图,而不是字符串列表。
这必须作为单个查询完成,而不是作为一个查询来获取所有客户,然后是每个客户的查询以获得余额(可能有数百万客户)
我知道grails会延迟加载,如果我想在每次查询播放器时强制grails加载帐户,但这会影响我想查找客户但不需要余额的时间。< / p>
我也知道我可以在grails中硬编码SQL / HQL,只是将结果作为字符串返回给gsp页面进行渲染,但这不是很粗糙的。
此外,我不想在播放器中为许多帐户添加链接,因为这可能会产生严重的性能影响,并且不是一般解决方案(我有大约400个域对象,并且需要很多连接查询解决方案)。
请注意,此示例假定每个玩家都有一个帐户。如果这不成立,我会使用外连接,如果我是通过SQL做的。不知道GORM中的等价物是什么。
有什么建议吗?
答案 0 :(得分:2)
因为我没有正确阅读而更新答案。
首先,您提到在视图中执行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])