Из этого туториала вы узнаете, как использовать 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 . |