如何在Grails中使用Where-Queries和DetachedCriteria?

时间:2016-06-14 18:43:09

标签: hibernate grails gorm hibernate-criteria detachedcriteria

EDIT1:我也接受答案,指导我重复使用DetachedCriteria而无需查询。在哪里查询是我的偏好,但如果常规DetachedCriteria不那么麻烦和更成熟,我愿意使用它。

我一直在试着把头包裹起来'现在在Grails中查询了一段时间。起初,我对它们的强大程度感到惊讶:我可以在不离开业务逻辑层的情况下构建查询。我认为它们是我遇到的一些性能问题的解决方案,这些问题涉及需要大量事务逻辑的复杂操作。

但是,我觉得文档中省略了查询所在的所有问题。我不知道如何在我的应用程序中使用它们,虽然我一直在阅读它们并且与它们玩弄很多。以下是我想要使用它们的方法:

在我的应用程序中,有很多子查询在使用HQL或本机SQL时是多余的,但是我不能重复使用它们,因为我不希望它们都被一个接一个地执行。我希望它们在一个数据库查询中执行。

就我而言,DetachedCriteria或在哪里查询是我的选择。我决定使用where查询,因​​为我比常规标准更喜欢这种方法和语法。

以下是问题:在许多版本中,我的查询被忽略!根据情况,我必须记住某个顺序或结构。

重用DetachedCriteria对象

我认为开发人员尝试做的最合乎逻辑的事情是封装经常用于查询并在需要时访问它们。所以,我把一些查询放在服务方法中,如下所示:

DetachedCriteria<Customer> allCustomersForProjektCriteria(DetachedCriteria<Customer> criteria, Project project){
    criteria.where{projekt == project}
}

我喜欢查询在理论上返回DetachedCriteria.对象的地方。也许这只是语法糖,我不知道。我尝试做类似的事情,至少可以说这种行为感觉很奇怪。

someService.allCustomersForProjectCriteria(Customer.where{name != null}, Project.get(1))
        .where{representatives {type != 'Manager'}}
        .list()

第一个查询以及我的服务方法中的一个工作正常,但最后一个没有。这就是我发现你只能在同一个方法或闭包中链接查询的方式。但那是预期的行为吗?类似的方法也可以在grails documentation&#34;查询组合&#34;中找到。

我将所有查询放在一个方法中的用例是什么?如果DetachedCriteria在某些情况下被默认忽略,那么DetachedCriteria where(Closure)如何提供方法Closure allCustomersForProjectCriteria(Project proj){ ({project == proj} as DetachedCriteria<Customer>) } 呢?为什么没有例外?

重用查询闭包的位置

我的下一个方法也在上面提到的grails文档的相同部分中提到。我没有将封装在不同方法中的查询链接在一起,而是试图封装闭包以随意重用它。我尝试了以下方法:

Customer.where(allCustomersForProjectCriteria(Projekt.get(1))
        .where{name != null && representatives {type != 'Manager'}}
        .list()

然后像这样使用它:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Error casting closure to grails.gorm.DetachedCriteria, Reason: null

    at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1276)

    at ConsoleScript148$_run_closure2.doCall(ConsoleScript148:9)

    at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1276)

    at ConsoleScript148.run(ConsoleScript148:12)

    at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1276)

现在,使用以下Stacktrace失败:

Closure allCustomersForProjectCriteria(Project proj){
    def criteria = {project == proj} as DetachedCriteria<Customer>
    criteria
}

我玩了一下,发现我不能声明闭包,投射它并在一行代码中返回它。我必须按如下方式重写我的方法:

    def additionalCriteria = {name != null && representatives {type != 'Manager'}} as DetachedCriteria<Customer>
    Customer.where(allCustomersForProjectCriteria(Projekt.get(1))
        .where(additionalCriteria)
        .list()

这是一个小麻烦,但我可以很容易地忍受它。我以为我现在都弄清楚了,因为没有例外。但是,同样,只有我的方法中的where查询被执行,另一个被忽略了。这就是我的困惑达到顶峰的地步。怎么了?这感觉不一致。如果在没有例外的情况下被忽略,我什么时候可以相信我的标准?

奇怪的是,如果我把第二个查询放在一个闭包中,它会再次起作用!!

def results = Customer.where{...}
        .where{...}
        .list()

现在谈谈......

所以这就是我尝试理解它的方法:我可以链接多个查询与新定义的闭包之后当且仅当它们位于相同的方法或闭包中

def getQuery(){
    Customer.where{...}
}
query.where{ ... } //This one is ignored

如果它们使用不同的方法,除了第一个忽略查询的方法之外的所有方法:

def getQuery(){Customer.where{...}}
def myWhereClosure = { ... }
query.where(myWhereClosure) //This one is NOT ignored anymore!

第一个是从一个方法或闭包中返回的,所以它不是正常的&#39;在哪里查询,它返回查询&#39;。方法调用时的闭包定义现在不起作用,我必须像这样使用它:

def getCustomerCrit(){
    def clos = {...} as DetachedCriteria<Customer>
    clos 
}
def results = Customer.where(customerCrit)
        .where{...} //This one is ignored
        .list()  

如果我封装了我的查询的闭包,它是一样的;一旦我执行一个查询,其中封装的where闭包作为参数,它现在返回到查询&#39;并且不能再定期使用了:

...

def additionalCrit = {...}
def results = Customer.where(customerCrit)
        .where(additionalCrit) //This one is NOT ignored anymore
        .list()  

所以,为了使它工作,我在查询的第二个地方使用预定义的闭包,这样它也可以返回查询&#39;并且不被忽视:

{{1}}

那么使用这些查询的目的是什么,它们是如何工作的?我在哪里可以找到关于该主题的更多资源而不是文档?

0 个答案:

没有答案