Перейти к основному содержимому

Метод addScalar() Hibernate

· 4 мин. чтения

1. Обзор

В этом кратком руководстве мы обсудим метод addScalar() , используемый в Hibernate, на примере. Мы узнаем, как использовать метод и преимущества его использования.

2. Какую проблему решает addScalar() ?

Обычно при получении результатов в Hibernate с помощью собственного SQL-запроса мы используем метод createNativeQuery() , за которым следует метод list() :

session.createNativeQuery("SELECT * FROM Student student")
.list();

В этом случае Hibernate использует ResultSetMetadata для поиска сведений о столбцах и возвращает список массивов объектов .

Но чрезмерное использование ResultSetMetadata может привести к снижению производительности, и именно здесь полезен метод addScalar() .

Используя метод addScalar() , мы можем запретить Hibernate использовать ResultSetMetadata .

3. Как использовать addScalar() ?

Давайте создадим новый метод для получения списка студентов с помощью метода addScalar() :

public List<Object[]> fetchColumnWithScalar() {
return session.createNativeQuery("SELECT * FROM Student student")
.addScalar("studentId", StandardBasicTypes.LONG)
.addScalar("name", StandardBasicTypes.STRING)
.addScalar("age", StandardBasicTypes.INTEGER)
.list();
}

Здесь нам нужно указать имя столбца и его тип данных в качестве аргументов метода addScalar() .

Теперь Hibernate не будет использовать ResultSetMetadata для получения сведений о столбце, поскольку мы определяем его заранее в addScalar(). Таким образом, мы получим лучшую производительность по сравнению с предыдущим подходом.

4. Другие преимущества

Давайте рассмотрим еще несколько вариантов использования, в которых мы можем использовать метод addScalar() .

4.1. Ограничение количества столбцов

Мы также можем использовать метод addScalar() , чтобы ограничить количество столбцов, возвращаемых нашим запросом .

Давайте напишем еще один метод fetchLimitedColumnWithScalar() для получения только столбца имени учащегося:

public List<String> fetchLimitedColumnWithScalar() {
return session.createNativeQuery("SELECT * FROM Student student")
.addScalar("name", StandardBasicTypes.STRING)
.list();
}

Здесь мы использовали звездочку в нашем запросе для получения списка студентов:

SELECT * FROM Student student

Но он не будет извлекать все столбцы и возвращает только одно имя столбца в списке , потому что мы указали только один столбец в методе addScalar() .

Давайте создадим метод JUnit для проверки столбца, возвращаемого методом fetchLimitedColumnWithScalar() :

List<String> list = scalarExample.fetchLimitedColumnWithScalar();
for (String colValue : list) {
assertTrue(colValue.startsWith("John"));
}

Как мы видим, это вернет список строк вместо массивов объектов . Кроме того, в нашем образце данных мы сохранили имена всех учащихся, начинающиеся с «Джон», и именно поэтому мы утверждаем значение столбцов против него в модульном тесте выше.

Это делает наш код более явным с точки зрения того, что он возвращает.

4.2. Возврат одного скалярного значения

Мы также можем использовать метод addScalar() для прямого возврата одного скалярного значения вместо списков.

Создадим метод, который возвращает средний возраст всех учеников:

public Integer fetchAvgAgeWithScalar() {
return (Integer) session.createNativeQuery("SELECT AVG(age) as avgAge FROM Student student")
.addScalar("avgAge")
.uniqueResult();
}

Теперь давайте проверим то же самое с помощью метода модульного тестирования: **

**

Integer avgAge = scalarExample.fetchAvgAgeWithScalar();
assertEquals(true, (avgAge >= 5 && avgAge <= 24));

Как мы видим, метод fetchAvgAgeScalar() напрямую возвращает значение Integer , и мы подтверждаем его.

В наших выборочных данных мы предоставили случайный возраст учащихся от 5 до 24 лет. Следовательно, во время утверждения мы ожидаем, что среднее значение будет между 5 и 24.

Точно так же мы можем использовать любые другие агрегатные функции в SQL, чтобы напрямую получить count , max , min , sum или любые другие одиночные скалярные значения, используя метод addScalar () .

5. Перегруженный метод addScalar() ``

У нас также есть перегруженный метод addScalar() , который принимает только имя столбца в качестве единственного аргумента .

Давайте создадим новый метод и воспользуемся перегруженным методом addScalar() , который извлекает столбец « возраст » без указания его типа:

public List<Object[]> fetchWithOverloadedScalar() {
return session.createNativeQuery("SELECT * FROM Student student")
.addScalar("name", StandardBasicTypes.STRING)
.addScalar("age")
.list();
}

Теперь давайте напишем еще один метод JUnit, чтобы проверить, возвращает ли наш метод два или более столбца:

List<Object[]> list = scalarExample.fetchColumnWithOverloadedScalar();
for (Object[] colArray : list) {
assertEquals(2, colArray.length);
}

Как мы видим, это возвращает список массивов объектов , а размер массива равен двум, что представляет столбцы имени и возраста в списке.

6. Заключение

В этой статье мы увидели использование метода addScalar() в Hibernate, как его использовать и когда использовать, а также пример.

Как всегда, код этих примеров доступен на GitHub .