本教程将展示如何使用Criteria API从数据库中搜索数据。 Criteria是功能强大的API,是HQL的优雅替代方案。
介绍
上一篇文章表明HQL是执行复杂查询的强大方法。 但是,如果HQL语句不固定并且需要连接,这不是很优雅。 例如:如果仅当参数不为null时才需要查询数据库,则我们的代码将如下所示:
def hqlQueryString = "from Person where 1 = 1"
def hqlNamedParams = [:]
if (firstNameToSearch != null) {
hqlQueryString = hqlQueryString + ' and firstName = :firstNameToSearch '
hqlNamedParams= hqlNamedParams + [firstNameToSearch:firstNameToSearch]
}
if (lastNameToSearch != null) {
hqlQueryString = hqlQueryString + ' and lastName = :lastNameToSearch '
hqlNamedParams= hqlNamedParams + [lastNameToSearch:lastNameToSearch]
}
def result = Person.executeQuery(hqlQueryString, hqlNamedParams)
如您所见,它可能很脏且难以维护。 它也容易出错。 条件是一种更优雅的选择。 新代码如下所示:
def criteria = Person.createCriteria()
def result = criteria.list {
if (firstNameToSearch != null) {
eq('firstName', firstNameToSearch)
}
if (lastNameToSearch != null) {
eq('lastName', lastNameToSearch)
}
}
现在,即使乍一看,该代码也更具可读性和易于理解。
准则方法
以下是条件实例的可用方法
清单
list方法将返回给定关闭条件的所有匹配行。
这将返回所有Person实例
def criteria = Person.createCriteria()
def result = criteria.list{}
这将返回所有名字为John的Person实例。
def criteria = Person.createCriteria()
def result = criteria.list{
eq ('firstName', 'John')
}
得到
给定关闭条件, get方法将返回一行。 请注意,当条件匹配多于1行时, get将引发异常。 如果没有匹配的行,则返回空值。
此示例将获得驾驶执照的Person实例。
def criteria = Person.createCriteria()
def result = criteria.get{
eq ('driverslicenseNo', 'C1922-8DFG-1155')
}
滚动
scroll方法将返回可滚动的结果集。 当您需要处理大量行时,这很有用,因为结果集将仅根据需要传输数据。
这是遍历姓氏为Doe的所有人的示例。
def criteria = Person.createCriteria()
def result = criteria.scroll{
eq ('lastName', 'Doe')
}
while (result.next()) {
def person = result.get()[0]
println "Hello ${person.firstName} ${person.lastName}"
}
AND OR运算子
我们可以使用and和or运算符来构造复杂的逻辑。
def criteria = Person.createCriteria()
def result = criteria.list {
or {
and {
eq('lastName', 'Doe')
gt('age', 15)
}
and {
eq('lastName', 'Smith')
gt('age', 18)
}
}
}
分页
我们可以通过传递offset和max参数来执行分页。 max参数是要返回的最大行数,而offset参数是在检索第一个结果之前要跳过的行数。
如果我们希望一次检索10行,下面是检索第一页的代码:
def criteria = Person.createCriteria()
def result = criteria.list (max:10, offset:0) {
eq ('firstName', 'John')
}
这是用于检索第二页的代码。 注意,唯一的区别是偏移量的值。
def criteria = Person.createCriteria()
def result = criteria.list (max:10, offset:0) {
eq ('firstName', 'John')
}
这是使用firstResult和maxResults检索第一页和第二页的另一种方法
def criteria = Person.createCriteria()
def result = criteria.list {
eq ('firstName', 'John')
firstResult(0)
maxResults(10)
}
def criteria = Person.createCriteria()
def result = criteria.list {
eq ('firstName', 'John')
firstResult(10)
maxResults(10)
}
强烈建议在进行分页时使用sort by子句。 这是有关如何按姓氏排序的示例:
def criteria = Person.createCriteria()
def result = criteria.list {
eq ('firstName', 'John')
order('lastName', 'asc')
firstResult(0)
maxResults(10)
}
投影
可以控制查询的结果列。 例如:
def criteria = Person.createCriteria()
def result = criteria.list {
projections {
property('firstName')
property('lastName')
}
}
而不是具有人员实例列表,它将返回一个二维列表。 以下是有关如何使用结果数据的示例代码:
def firstPerson = result[0]
def firstName = firstPerson[0]
def lastName = firstPerson[1]
println "First Name = ${firstName}"
println "Last Name = ${lastName}"
汇总功能
与SQL相似,也可以在条件内使用聚合函数。
- 独特 –这是一个有关如何检索数据库中所有唯一姓氏的示例
def criteria = Person.createCriteria() def result = criteria.list { projections { distinct('lastName') } } println "Here are the list of unique last names" result.each { lastName -> println "${lastName}" } - 平均 -这是有关如何获得所有人平均年龄的示例
def criteria = Person.createCriteria() def result = criteria.list { projections { avg('age') } } println "The average age is ${result[0]}" - count –这是有关如何获取人员表中记录数的示例
def criteria = Person.createCriteria() def result = criteria.list { projections { count() } } println "The number of rows is ${result[0]}" - sum –这是有关如何使用sum的示例
def criteria = Purchase.createCriteria() def result = criteria.list { projections { sum('price') } } println "The sum of all price ${result[0]}" - max和min –这是如何使用max和min的示例
def criteria = Person.createCriteria() def result = criteria.list { projections { max('age') min('age') } } println "The maximum age is ${result[0][0]}" println "The minimum age is ${result[0][1]}"
其他标准示例
以下是有关如何过滤结果的其他示例。
- 属性值比较 –可以将域属性与特定值进行比较。 以下是一些相关标准: eq , gt , ge , lt , le和ne 。
以下是示例代码,列出了所有姓Doe的青少年:def criteria = Person.createCriteria() def result = criteria.list { eq('lastName', 'Doe') ge('age', 13) le('age', 17) } - 属性到属性比较 –可以将域属性与另一个属性进行比较。 以下是一些相关条件: eqProperty , gtProperty , geProperty , ltProperty , leProperty和neProperty 。
这是一个示例代码,列出了所有与名字相同的人:def criteria = Person.createCriteria() def result = criteria.list { eqProperty('firstName', 'lastName') } - 测试null值 – isNull和isNotNull可用于检查域属性是否为null。 这是一个示例,列出了所有没有名字编码的人:
def criteria = Person.createCriteria() def result = criteria.list { isNull('firstName') }
有关其他条件,请参阅最新的Grails文档。
翻译自: https://www.javacodegeeks.com/2015/02/grails-tutorial-for-beginners-criteria-api.html
本文介绍Grails框架中的Criteria API,一种用于数据库查询的优雅替代方案,提供了list、get、scroll等方法,支持AND、OR逻辑,分页查询,属性值比较等功能。
4518

被折叠的 条评论
为什么被折叠?



