Есть ли способ получить размер счета для именованного запроса JPA с набором результатов? - PullRequest
16 голосов
/ 18 февраля 2010

Мне нравится идея именованных запросов в JPA для статических запросов, которую я собираюсь сделать, но я часто хочу получить результат подсчета для запроса, а также список результатов из некоторого подмножества запроса. Я бы не стал писать два почти идентичных NamedQueries. В идеале, я хотел бы иметь что-то вроде:

@NamedQuery(name = "getAccounts", query = "SELECT a FROM Account")
.
.
  Query q = em.createNamedQuery("getAccounts");
  List r = q.setFirstResult(s).setMaxResults(m).getResultList();
  int count = q.getCount();

Итак, допустим, что m равно 10, s равно 0, и в Account имеется 400 строк. Я ожидаю, что в r будет список из 10 элементов, но я бы хотел знать, что всего 400 строк. Я мог бы написать второй @NamedQuery:

@NamedQuery(name = "getAccountCount", query = "SELECT COUNT(a) FROM Account")

но кажется СУХОЕ нарушение, если я всегда просто хочу подсчитать. В этом простом случае легко синхронизировать эти два параметра, но если запрос изменяется, кажется, что не совсем идеально, что мне нужно обновить оба @NamedQueries, чтобы сохранить значения в строке.

Обычным вариантом использования здесь будет выборка некоторого подмножества элементов, но при этом потребуется некоторый способ указания общего количества («Отображение 1-10 из 400»).

Ответы [ 3 ]

13 голосов
/ 10 октября 2010

Таким образом, в итоге я решил создать два @NamedQuerys, один для результирующего набора и один для счетчика, но захват базового запроса в статической строке для поддержания DRY и обеспечения согласованности обоих запросов. Так что для вышесказанного, у меня было бы что-то вроде:

@NamedQuery(name = "getAccounts", query = "SELECT a" + accountQuery)
@NamedQuery(name = "getAccounts.count", query = "SELECT COUNT(a)" + accountQuery)
.
static final String accountQuery = " FROM Account";
.
  Query q = em.createNamedQuery("getAccounts");
  List r = q.setFirstResult(s).setMaxResults(m).getResultList();
  int count = ((Long)em.createNamedQuery("getAccounts.count").getSingleResult()).intValue();

Очевидно, что в этом примере тело запроса тривиально, и это излишне. Но с гораздо более сложными запросами вы получаете единственное определение тела запроса и можете убедиться, что оба запроса синхронизированы. Вы также получаете преимущество в том, что запросы предварительно компилируются и, по крайней мере, с Eclipselink, вы получаете проверку во время запуска, а не при вызове запроса.

Путем согласованного именования между двумя запросами можно обернуть тело кода для запуска обоих наборов, просто используя базовое имя запроса.

5 голосов
/ 18 февраля 2010

Использование setFirstResult / setMaxResults do not возвращает подмножество набора результатов, запрос даже не запускался при вызове эти методы влияют на сгенерированный запрос SELECT, который будет выполняться при вызове getResultList. Если вы хотите получить общее количество записей, вам придется SELECT COUNT ваших сущностей в отдельном запросе (обычно перед разбивкой на страницы).

Для полного примера посмотрите Разбиение на страницы наборов данных в образце приложения с использованием JSF, сеанса без сохранения состояния фасада каталога и Java Persistence API .

1 голос
/ 28 июня 2011

о, ну, вы можете использовать самоанализ для получения аннотаций именованных запросов, таких как:

String getNamedQueryCode(Class<? extends Object> clazz, String namedQueryKey) {
    NamedQueries namedQueriesAnnotation = clazz.getAnnotation(NamedQueries.class);
    NamedQuery[] namedQueryAnnotations = namedQueriesAnnotation.value();

    String code = null;
    for (NamedQuery namedQuery : namedQueryAnnotations) {
        if (namedQuery.name().equals(namedQueryKey)) {
            code = namedQuery.query();
            break;
        }
    }

    if (code == null) {
        if (clazz.getSuperclass().getAnnotation(MappedSuperclass.class) != null) {
            code = getNamedQueryCode(clazz.getSuperclass(), namedQueryKey);
        }
    }

    //if not found
    return code;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...