Статьи

Учебник Grails для начинающих — Критерии API

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

  • Отличный — вот пример того, как получить все уникальные фамилии в базе данных
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    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 — вот пример того, как получить средний возраст всех людей
    1
    2
    3
    4
    5
    6
    7
    def criteria = Person.createCriteria()
    def result = criteria.list {
        projections {
            avg('age')
        }
    }
    println "The average age is ${result[0]}"
  • count — вот пример того, как получить количество записей в таблице person
    1
    2
    3
    4
    5
    6
    7
    def criteria = Person.createCriteria()
    def result = criteria.list {
        projections {
            count()
        }
    }
    println "The number of rows is ${result[0]}"
  • сумма — вот пример того, как использовать сумму
    1
    2
    3
    4
    5
    6
    7
    def criteria = Purchase.createCriteria()
    def result = criteria.list {
        projections {
            sum('price')
        }
    }
    println "The sum of all price ${result[0]}"
  • max и min — вот пример того, как использовать max и min
    1
    2
    3
    4
    5
    6
    7
    8
    9
    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 .
    Вот пример кода, в котором перечислены все подростки с фамилией Доу:

    1
    2
    3
    4
    5
    6
    def criteria = Person.createCriteria()
    def result = criteria.list {
        eq('lastName', 'Doe')
        ge('age', 13)
        le('age', 17)
    }
  • Сравнение свойства с свойством — свойство домена можно сравнить с другим свойством. Вот несколько связанных критериев: eqProperty , gtProperty , geProperty , ltProperty , leProperty и neProperty .
    Вот пример кода, который перечисляет всех людей, чье имя совпадает с его фамилией:

    1
    2
    3
    4
    def criteria = Person.createCriteria()
    def result = criteria.list {
        eqProperty('firstName', 'lastName')
    }
  • Проверить нулевое значениеisNull и isNotNull можно использовать для проверки, является ли свойство домена нулевым или нет. Вот пример, который перечисляет всех людей, которые закодированы без имени:
    1
    2
    3
    4
    def criteria = Person.createCriteria()
    def result = criteria.list {
        isNull('firstName')
    }

Для другого критерия, обратитесь к последнему документу Grails.

Ссылка: Учебник Grails для начинающих — Критерии API от нашего партнера JCG Джонатана Тана в блоге Grails .