我在Grails中有两个非常相似的方法,比如“按os计算统计数据”和“通过浏览器计算统计数据” - 有效地准备一些东西,然后在数据库上运行类似的查询,然后对结果做一些事情。方法不同的唯一部分是它们在我的方法中运行的查询 -
def summary = c.list {
eq('browser', Browser.get(1)) // OR eq('os', OS.get(1))
between('date', dates.start, dates.end)
}
我想到重构它的理想方法是将闭包的第一行作为方法参数传递。像
doStats (Closure query) {
...
def summary = c.list {
query
between('date', dates.start, dates.end)
}
}
我试过了,但“查询”被忽略了。我尝试使用query()但是然后在定义的地方执行查询子句,因此这也不起作用。我想我可以将整个闭包作为参数传递,但这似乎是错误的 - 查询可能在将来变得更复杂。
任何人都有更好的想法吗?
答案 0 :(得分:3)
你使用的标准DSL可能与普通常规封闭不同。
要做你要问的事,你可以使用这里描述的方法 -
http://mrhaki.blogspot.com/2010/06/grails-goodness-refactoring-criteria.html
并将您的查询放入私有方法。
更优雅的解决方案是在grails中使用命名查询 -
http://grails.org/doc/latest/ref/Domain%20Classes/namedQueries.html
看看
recentPublicationsWithBookInTitle {
// calls to other named queries…
recentPublications()
publicationsWithBookInTitle()
}
示例 -
答案 1 :(得分:3)
我发现leftShift
运算符对于从两个独立的组合构成闭包很有用。你能做的是:
Closure a = { /*...*/ }
Closure b = { /*...*/ }
Closure c = a << b
看一下这个例子:
def criteria = {
projection Projections.distinct(Projections.property('id'))
and {
eq 'owner.id', userDetails.id
if (filter.groupId) {
eq 'group.id', filter.groupId
}
}
}
List<Long> ids = Contact.createCriteria().list(criteria << {
maxResults filter.max
firstResult filter.offset
})
Integer totalCount = Contact.createCriteria().count(criteria)
你在这里看到的是我创建了一个criteria
来列出计数GORM对象的蚁群。两个案例的标准几乎相同,但出于列表目的,我还需要包含命令对象的限制和偏移量。
答案 2 :(得分:2)
对Grails Criteria构建器不确定,但对于其他构建器,您可以执行以下操作:
doStats (Closure query) {
def summary = c.list {
query( it )
between('date', dates.start, dates.end)
}
}
并通过以下方式致电:
def f = { criteria ->
criteria.eq( 'browser', Browser.get( 1 ) )
}
doStats( f )
如果没有,您可能最好查看命名查询like tomas says