Есть ли способ получить размер подсчета для JPA с именем Query с набором результатов?

StackOverflow https://stackoverflow.com/questions/2285270

  •  21-09-2019
  •  | 
  •  

Вопрос

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

@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, а в учетной записи есть 400 строк. Я ожидаю, что у R будет список из 10 пунктов, но я бы хотел знать, что всего 400 строк. Я мог бы написать второй @namedquery:

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

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

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

Это было полезно?

Решение

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

@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, вы получаете проверку во время запуска вместо того, когда вы называете запрос.

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

Другие советы

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

Для получения полного примера проверьте Пеенью наборов данных в примере приложения с использованием JSF, сеанса без факультета фасада и API -интерфейсов Java Storyse Apis.

О, хорошо, вы можете использовать самоанализ, чтобы получить название аннотаций запросов, например:

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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top