У меня есть метод, который создает и выполняет запрос Criteria. Запрос делает то, что я хочу, в частности, он фильтрует (и сортирует) записи на основе ввода пользователя.
Кроме того, размер запроса ограничен количеством записей на экране. Это важно, потому что таблица данных может быть очень большой.
Однако, если применяются фильтры, я хочу подсчитать количество записей, которые будут возвращены, если запрос не был ограничен. Таким образом, это означает выполнение двух запросов: один для извлечения записей, а затем один для подсчета записей, которые находятся в общем наборе. Это выглядит так:
public List<Log> runQuery(TableQueryParameters tqp) {
// get the builder, query, and root
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Log> query = builder.createQuery(Log.class);
Root<Log> root = query.from(Log.class);
// build the requested filters
Predicate filter = null;
for (TableQueryParameters.FilterTerm ft : tqp.getFilterTerms()) {
// this section runs trough the user input and constructs the
// predicate
}
if (filter != null) query.where(filter);
// attach the requested ordering
List<Order> orders = new ArrayList<Order>();
for (TableQueryParameters.SortTerm st : tqp.getActiveSortTerms()) {
// this section constructs the Order objects
}
if (!orders.isEmpty()) query.orderBy(orders);
// run the query
TypedQuery<Log> typedQuery = em.createQuery(query);
typedQuery.setFirstResult((int) tqp.getStartRecord());
typedQuery.setMaxResults(tqp.getPageSize());
List<Log> list = typedQuery.getResultList();
// if we need the result size, fetch it now
if (tqp.isNeedResultSize()) {
CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
countQuery.select(builder.count(countQuery.from(Log.class)));
if (filter != null) countQuery.where(filter);
tqp.setResultSize(em.createQuery(countQuery).getSingleResult().intValue());
}
return list;
}
В результате я дважды вызываю createQuery для одного и того же CriteriaBuilder и делю объект Predicate (фильтр) между ними обоими. Когда я запускаю второй запрос, я иногда получаю следующее сообщение:
Исключение [EclipseLink-6089] (Eclipse Persistence Services -
2.2.0.v20110202-r8913):
org.eclipse.persistence.exceptions.QueryException Exception
Описание: выражение не было правильно инициализировано. Только
один запрос ExpressionBuilder должен использоваться для запроса. Для параллельного
выражений, класс запроса должен быть предоставлен ExpressionBuilder
конструктор, и ExpressionBuilder запроса всегда должен быть на
левая сторона выражения. Выражение: [База
com.myqwip.database.Log] Запрос: ReportQuery (referenceClass = Log) в
org.eclipse.persistence.exceptions.QueryException.noExpressionBuilderFound (QueryException.java:874)
в
org.eclipse.persistence.expressions.ExpressionBuilder.getDescriptor (ExpressionBuilder.java:195)
в
org.eclipse.persistence.internal.expressions.DataExpression.getMapping (DataExpression.java:214)
Может кто-нибудь сказать мне, почему эта ошибка появляется периодически, и что я должен сделать, чтобы это исправить?