Из этого туториала вы узнаете, как использовать Criteria API для поиска данных в базе данных. Критерии — это мощный API и элегантная альтернатива HQL.
Вступление
Этот предыдущий пост показал, что HQL является мощным способом выполнения сложных запросов. Тем не менее, это не очень элегантно, если HQL-оператор не является фиксированным и требует объединения. Например: если нам нужно запрашивать базу данных, только если параметр не равен NULL, наш код будет выглядеть следующим образом:
01
02
03
04
05
06
07
08
09
10
11
|
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) |
Как вы могли видеть, это может быть грязным и громоздким в обслуживании. Это также подвержено ошибкам. Критерии — более элегантная альтернатива. Вот как будет выглядеть новый код:
1
2
3
4
5
6
7
8
9
|
def criteria = Person.createCriteria() def result = criteria.list { if (firstNameToSearch != null ) { eq( 'firstName' , firstNameToSearch) } if (lastNameToSearch != null ) { eq( 'lastName' , lastNameToSearch) } } |
Код теперь более читабелен и понятен даже с одного взгляда.
Критериальные методы
Вот доступные методы для экземпляра критерия
список
Метод list вернет все соответствующие строки заданных критериев закрытия.
Это вернет все экземпляры Person
1
2
|
def criteria = Person.createCriteria() def result = criteria.list{} |
Это вернет все экземпляры Person с именем John
1
2
3
4
|
def criteria = Person.createCriteria() def result = criteria.list{ eq ( 'firstName' , 'John' ) } |
получить
Метод get вернет одну строку с учетом критериев закрытия. Обратите внимание, что get выдаст исключение, когда критерии соответствуют более чем 1 строке. Если ни одна строка не соответствует, возвращается нулевое значение.
В этом примере экземпляр Person получит водительские права.
1
2
3
4
|
def criteria = Person.createCriteria() def result = criteria.get{ eq ( 'driverslicenseNo' , 'C1922-8DFG-1155' ) } |
свиток
Метод scroll возвращает прокручиваемый набор результатов. Это полезно, когда вам нужно работать с большим количеством строк, так как результирующий набор будет передавать данные только по мере необходимости.
Вот пример перебора всех людей с фамилией Доу.
1
2
3
4
5
6
7
8
|
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 и или для построения сложной логики.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
def criteria = Person.createCriteria() def result = criteria.list { or { and { eq( 'lastName' , 'Doe' ) gt( 'age' , 15 ) } and { eq( 'lastName' , 'Smith' ) gt( 'age' , 18 ) } } } |
пагинация
Мы можем выполнить разбиение на страницы, передав параметры смещения и максимума . Параметр max — это максимальное количество строк, которые должны быть возвращены, а параметр смещения — это количество строк, которые нужно пропустить до получения первого результата.
Если мы хотим получить 10 строк за раз, вот код для получения первой страницы:
1
2
3
4
|
def criteria = Person.createCriteria() def result = criteria.list (max: 10 , offset: 0 ) { eq ( 'firstName' , 'John' ) } |
А вот и код для извлечения второй страницы. Обратите внимание, что единственная разница — это значение для смещения.
1
2
3
4
|
def criteria = Person.createCriteria() def result = criteria.list (max: 10 , offset: 0 ) { eq ( 'firstName' , 'John' ) } |
Вот альтернативный способ получения первой и второй страницы, используя firstResult и maxResults
1
2
3
4
5
6
|
def criteria = Person.createCriteria() def result = criteria.list { eq ( 'firstName' , 'John' ) firstResult( 0 ) maxResults( 10 ) } |
1
2
3
4
5
6
|
def criteria = Person.createCriteria() def result = criteria.list { eq ( 'firstName' , 'John' ) firstResult( 10 ) maxResults( 10 ) } |
Настоятельно рекомендуется иметь сортировку по пунктам при выполнении нумерации страниц. Вот пример того, как сортировать по фамилии:
1
2
3
4
5
6
7
|
def criteria = Person.createCriteria() def result = criteria.list { eq ( 'firstName' , 'John' ) order( 'lastName' , 'asc' ) firstResult( 0 ) maxResults( 10 ) } |
проекция
Можно контролировать результирующие столбцы запроса. Например:
1
2
3
4
5
6
7
|
def criteria = Person.createCriteria() def result = criteria.list { projections { property( 'firstName' ) property( 'lastName' ) } } |
Вместо того, чтобы иметь список экземпляров персонажа, он вернет двумерный список. Вот пример кода о том, как использовать данные результата:
1
2
3
4
5
|
def firstPerson = result[ 0 ] def firstName = firstPerson[ 0 ] def lastName = firstPerson[ 1 ] println "First Name = ${firstName}" println "Last Name = ${lastName}" |
Агрегатные функции
Подобно SQL, также можно использовать агрегатные функции внутри критериев.
- Отличный — вот пример того, как получить все уникальные фамилии в базе данных
01020304050607080910
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}"
}
- avg — вот пример того, как получить средний возраст всех людей
1234567
def criteria = Person.createCriteria()
def result = criteria.list {
projections {
avg(
'age'
)
}
}
println
"The average age is ${result[0]}"
- count — вот пример того, как получить количество записей в таблице person
1234567
def criteria = Person.createCriteria()
def result = criteria.list {
projections {
count()
}
}
println
"The number of rows is ${result[0]}"
- сумма — вот пример того, как использовать сумму
1234567
def criteria = Purchase.createCriteria()
def result = criteria.list {
projections {
sum(
'price'
)
}
}
println
"The sum of all price ${result[0]}"
- max и min — вот пример того, как использовать max и min
123456789
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 .
Вот пример кода, в котором перечислены все подростки с фамилией Доу:123456def criteria = Person.createCriteria()
def result = criteria.list {
eq(
'lastName'
,
'Doe'
)
ge(
'age'
,
13
)
le(
'age'
,
17
)
}
- Сравнение свойства с свойством — свойство домена можно сравнить с другим свойством. Вот несколько связанных критериев: eqProperty , gtProperty , geProperty , ltProperty , leProperty и neProperty .
Вот пример кода, который перечисляет всех людей, чье имя совпадает с его фамилией:1234def criteria = Person.createCriteria()
def result = criteria.list {
eqProperty(
'firstName'
,
'lastName'
)
}
- Проверить нулевое значение — isNull и isNotNull можно использовать для проверки, является ли свойство домена нулевым или нет. Вот пример, который перечисляет всех людей, которые закодированы без имени:
1234
def criteria = Person.createCriteria()
def result = criteria.list {
isNull(
'firstName'
)
}
Для другого критерия, обратитесь к последнему документу Grails.
Ссылка: | Учебник Grails для начинающих — Критерии API от нашего партнера JCG Джонатана Тана в блоге Grails . |