Предположим, у меня есть таблица, которая содержит все учетные записи пользователей и типов. Я хочу создать метод Jpa Repository, который возвращает массив общего числа пользователей каждого типа (USER, ADMIN, MASTER).

Вот как я это сделал в JpaRepository:

@Query(value="SELECT   (SELECT COUNT(*) FROM account WHERE account_role='USER'),"
                        + "(SELECT COUNT(*) FROM account WHERE account_role='ADMIN'),"
                        + "(SELECT COUNT(*) FROM account WHERE account_role='MASTER')"
                        + "FROM account LIMIT 1",
            nativeQuery=true)
public List<Integer> getTotalAccountType();

Код выполнялся нормально, но результат оказался не таким, как я ожидал.

Результат : [2]

Ожидаемый результат: [2,10,30]

Любая идея, как бы я использовать вложенный SQL с JPQL? Заранее спасибо!

1
Nhok V 19 Июл 2019 в 19:26

2 ответа

Лучший ответ

Попробуйте вернуть Object[], а не List<Integer>. Я думаю, что возврат List<Integer> будет означать, что возвращаются несколько строк значения Integer, тогда как вы возвращаетесь на одну строку с несколькими Intger столбцами.

Из полученного Object[] вы вытащите первое значение (указывающее на строку). Это должен быть еще один Object[], который будет иметь ваши значения в порядке возврата.

Вы также можете удалить эту последнюю "FROM account LIMIT 1" строку, так как она не имеет отношения к результату.

Я бы порекомендовал привести все это к объекту. Как видно здесь - Как вернуть пользовательский объект из запроса Spring BY JPA GROUP BY

0
Corey 19 Июл 2019 в 17:45

Если метод репозитория возвращает список целых чисел, это означает, что строка результата запроса содержит целочисленное значение. Но вы ожидаете получить последовательность целых чисел в одном ряду.

Вы можете получить тот же результат другим способом:

@Query(value="SELECT COUNT(*) FROM account WHERE account_role=?", nativeQuery=true)
public Integer getTotalAccountType(String role);

А потом:

Integer userCount = repository.getTotalAccountType("USER");
Integer adminCount = repository.getTotalAccountType("ADMIN");
Integer masterCount = repository.getTotalAccountType("MASTER");

Или если вы сопоставили сущность:

  1. создать класс Pair<K,V> с помощью конструктора Pair(K key, V value) или использовать его из любого внешняя библиотека
  2. метод репозитория на основе запроса hql

    @Query(value="select new javafx.util.Pair(a.accountRole, count(a)) from Account a group by a.accountRole") public List<Pair<String, Integer>> getRoleCountList();

  3. преобразовать результат хранилища в Map<String, Integer> в службе

    javafx.util.Pair<String, Integer> result = repository.getRoleCountList(); Map<String, Integer> map = result.stream().collect(Collectors.toMap(r-> r.getKey(), r-> r.getValue()));

2
alex valuiskyi 19 Июл 2019 в 20:23