GORM 查询的代码重构
Code Refactoring of a GORM query
我写了一个代码来从我的数据库中获取一些实体,但代码非常丑陋(代码重复等)并且对于大块实体来说不是很快。
该代码获取所有实体,然后对其进行排序(在内存中),然后获取一系列项目(用于对结果进行分页)。
就是这样:
List<T> retrieveData() {
def filterPastEvents = (params.filterPastEvents) ?: 0
def entities = retrieveUnsortedData(filterPastEvents).sort {
entity1, entity2 ->
entity2.criterion1 <=> entity1.criterion1 ?:
entity1.criterion2 <=> entity2.criterion2 ?:
entity1.criterion3 <=> entity2.criterion3
}
if (params.offset != null && params.max != null) {
return entities.subList(params.offset, Math.min(params.to+1,entities.size()))
} else {
return entities
}
}
private List<Entity> retrieveUnsortedData(filterPastEvents) {
List<Entity> entityList
if (params.param1 && params.params2) {
entityList = Entity.findAll({
param1 == params.param1
params2 == params.params2
endTimeUTC >= filterPastEvents
})
}
if (params.param1 && !params.params2) {
entityList = Entity.findAll({
param1 == params.param1
endTimeUTC >= filterPastEvents
})
}
if (params.params2 && !params.param1) {
entityList = Entity.findAll({
params2 == params.params2
endTimeUTC >= filterPastEvents
})
}
if (entityList == null) {
entityList = Entity.findAll({
endTimeUTC >= filterPastEvents
})
}
return entityList
}
虽然这段代码有效.
,但我认为使用标准而不使用重复代码会更有效
这就是我试图简化代码的原因:
List<T> retrieveData() {
def filterPastEvents = (params.filterPastEvents) ?: 0
Closure closureOrder = {
endTimeUTC >= filterPastEvents
order('criteria1', 'desc')
order('criteria2', 'asc')
order('criteria3', 'desc')
}
Closure param1Closure = {}
if (params.param1) {
param1Closure = {
param1 == params.param1
}
}
Closure param2Closure = {}
if (params.param2) {
param2Closure = {
param2 == params.param2
}
}
return Entity.findAll(max: params.max, offset: params.offset).list {
param1Closure
param2Closure
closureOrder
}
}
此时我的问题是:
闭包不是 'run',param1 和 param2 的条件不正确。
和这段代码
Closure param1Closure = {}
if (params.param1) {
param1Closure = {
param1 == params.param1
}
}
仍然与 param2 重复。
如何根据条件(即:params.param1?)编写闭包,我尝试使用 Closure c << param1Closure 但它似乎不起作用。
这里有一个更简单的方法:
List<T> retrieveData() {
Entity.findAll(max: params.max, offset: params.offset) {
if(params.param1) param1 == params.param1
if(params.param2) param2 == params.param2
if(params.filterPastEvents) endTimeUTC >= filterPastEvent
order 'criteria1', 'desc'
order 'criteria2', 'asc'
order 'criteria3', 'desc'
}
}
上面的例子还是比较简洁的,但是如果你真的要用composition的话,可以compose where queries。像这样:
import grails.gorm.DetachedCriteria
List<T> retrieveData() {
...
DetachedCriteria<Entity> param1Closure = (params.param1 ? { param1 == params.param1 } : { }) as DetachedCriteria<Entity>
...
def query = Entity.where(param1Closure)
query = query.where(param2Closure)
query = query.where(closureOrder)
return query.list(max: params.max, offset: params.offset)
}
关键是如果你用一个变量作为闭包调用where(Closure)
,那么闭包必须转换为DetachedCriteria
。常规关闭将不起作用。
我写了一个代码来从我的数据库中获取一些实体,但代码非常丑陋(代码重复等)并且对于大块实体来说不是很快。 该代码获取所有实体,然后对其进行排序(在内存中),然后获取一系列项目(用于对结果进行分页)。
就是这样:
List<T> retrieveData() {
def filterPastEvents = (params.filterPastEvents) ?: 0
def entities = retrieveUnsortedData(filterPastEvents).sort {
entity1, entity2 ->
entity2.criterion1 <=> entity1.criterion1 ?:
entity1.criterion2 <=> entity2.criterion2 ?:
entity1.criterion3 <=> entity2.criterion3
}
if (params.offset != null && params.max != null) {
return entities.subList(params.offset, Math.min(params.to+1,entities.size()))
} else {
return entities
}
}
private List<Entity> retrieveUnsortedData(filterPastEvents) {
List<Entity> entityList
if (params.param1 && params.params2) {
entityList = Entity.findAll({
param1 == params.param1
params2 == params.params2
endTimeUTC >= filterPastEvents
})
}
if (params.param1 && !params.params2) {
entityList = Entity.findAll({
param1 == params.param1
endTimeUTC >= filterPastEvents
})
}
if (params.params2 && !params.param1) {
entityList = Entity.findAll({
params2 == params.params2
endTimeUTC >= filterPastEvents
})
}
if (entityList == null) {
entityList = Entity.findAll({
endTimeUTC >= filterPastEvents
})
}
return entityList
}
虽然这段代码有效.
,但我认为使用标准而不使用重复代码会更有效
这就是我试图简化代码的原因:
List<T> retrieveData() {
def filterPastEvents = (params.filterPastEvents) ?: 0
Closure closureOrder = {
endTimeUTC >= filterPastEvents
order('criteria1', 'desc')
order('criteria2', 'asc')
order('criteria3', 'desc')
}
Closure param1Closure = {}
if (params.param1) {
param1Closure = {
param1 == params.param1
}
}
Closure param2Closure = {}
if (params.param2) {
param2Closure = {
param2 == params.param2
}
}
return Entity.findAll(max: params.max, offset: params.offset).list {
param1Closure
param2Closure
closureOrder
}
}
此时我的问题是:
闭包不是 'run',param1 和 param2 的条件不正确。
和这段代码
Closure param1Closure = {}
if (params.param1) {
param1Closure = {
param1 == params.param1
}
}
仍然与 param2 重复。
如何根据条件(即:params.param1?)编写闭包,我尝试使用 Closure c << param1Closure 但它似乎不起作用。
这里有一个更简单的方法:
List<T> retrieveData() {
Entity.findAll(max: params.max, offset: params.offset) {
if(params.param1) param1 == params.param1
if(params.param2) param2 == params.param2
if(params.filterPastEvents) endTimeUTC >= filterPastEvent
order 'criteria1', 'desc'
order 'criteria2', 'asc'
order 'criteria3', 'desc'
}
}
上面的例子还是比较简洁的,但是如果你真的要用composition的话,可以compose where queries。像这样:
import grails.gorm.DetachedCriteria
List<T> retrieveData() {
...
DetachedCriteria<Entity> param1Closure = (params.param1 ? { param1 == params.param1 } : { }) as DetachedCriteria<Entity>
...
def query = Entity.where(param1Closure)
query = query.where(param2Closure)
query = query.where(closureOrder)
return query.list(max: params.max, offset: params.offset)
}
关键是如果你用一个变量作为闭包调用where(Closure)
,那么闭包必须转换为DetachedCriteria
。常规关闭将不起作用。