在 Grails 中利用闭包实现查询条件的动态构造

      在 Javascript 中,闭包可以做出许多精彩漂亮的活儿,同样,利用 Groovy 的闭包特性,也能实现在Java中需要很曲折才达到的任务(java7吗?是的,但还得等等我们的 Oracle 到2012了)。在 Groovy 社区,提及 Groovy,必会提到如影随形的 Grails, 下面我们通过一个实例体会一下 Groovy 闭包在 Grails 中的精彩运用。

 

      假设我们要实现如下一个功能:在一个查询功能模块中,我想动态添加一些额外的查询条件,使得查询结果进一步缩小,按需返回不同的结果集。相比较最原始的 SQL 拼接,利用 Grails GORM 的强大威力再加上 Groovy 的闭包特性,实现将变得更加优雅和 Cool!

 

一. 首先定义 两个Domain

class 1 : Company

class Company{
    ...

    String name

    static hasMany = [departments: Department]

    ...
}

 

class 2 : Department

class Department  {
    ...
    
    String name
    boolean enabled = true 
    boolean shared
    int employeeCount //部门的员工数
    Company owner     //部门所属的企业

    static belongsTo = [owner: Company]

    static constraints = {owner(nullable: false)}

	/**
	 * 
	 * @param params 查询的通用参数Map. eg:[max:10, offset:20, sort:'name', order:'asc']
	 * @param otherParams 其他查询参数Map. eg:[ilikeName:'山东', callback:{...}] 
	 * @return
	 */
    def availableList(params, otherParams) {
        def c = createCriteria()
        return c.list(max: params.max, offset: params.offset) {
            if(otherParams.ilikeName)
                ilike('name',"%${otherParams.ilikeName}%")
            eq('blankItem', false)
            eq('enabled', true)
            if (otherParams.callback) {
                Closure callback = otherParams.callback;
                callback.delegate  = c
                callback()
            }
            order(params.sort, params.order)
        }
    }
    
    ...
}
 
二. 如何实现动态查询的构造呢,利用Groovy 弱类型语言的优势,在 otherParams Map 中存储一个动态构造的 GORM DSL 查询闭包即可。下面是调用代码:

 

...

def otherParams = []
otherParams.callback = {
    eq('employeeCount', 3)
    owner{
        eq("id", Long.parseLong(params.ownerID))
    }
}

Department dept = new Department()
def list = dept.availableList(params, otherParams)

...
 上述调用代码意思是我想把查询的结果集进一步限制为“指定 的公司ID中,有3个员工的所有部门".

 


三.下面对几处关键代码加以解释:

1.
if (otherParams.callback) {   
    Closure _callback = otherParams.callback;
    _callback.delegate  = c
    _callback()
}

  如果在参数 otherParams 中定义了 key 为 ‘callback’ 的 Map Entry,则将其 value 为 GORM DSL 查询闭包传给 _callback 的这个 Closure 类型,随后,最关键的一点是 callback.delegate  = c , 以使得此处能正确回调动态传入的 GORM  DSL 查询闭包体

 

2.

otherParams.callback = {
    eq('employeeCount', 3)    
    owner{
        eq("id", Long.parseLong(params.ownerID))
    }
}

在调用方的 otherParams 中增加一项 key 为 'callback' 的 Map Entry , 并构造了一个常规的 Grails DSL 查询闭包体,意思是"指定的公司ID中,有3个员工的所有部门".

 

至此,你就可以根据你自己的需要构造

otherParams.callback = {...}

 

。你还可以举一翻三,做出更多有创意的事情。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值