Проблема:
Если запрос строится на Criteria API, то существует баг, воспроизводимый при попытке count-запроса для сущности с составным первичным ключом (composite primary key).
Ошибка при этом звучит так:
Причина:
Запрос формируется в таком виде:
Дело в том, что Hibernate сам ищет идентификаторы сущности и подставляет в count их, а не wildcard (*).
Изучение жалоб говорит о том, что полученный запрос не воспринимается oracle, mysql, зато выполняется в mssql.
Есть также и открытый дефект на трекере Hibernat'а: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5419
Впрочем, он открыт уже почти год. А потому быстрее найти способ обойти проблему, чем ждать централизованного решения.
Решение:
На полноценное решение не тянет, но, уверен, поможет 95% столкнувшихся с проблемой.
Как правило составной идентификатор состоит из нескольких внешних ключей. И наверняка хоть один из них not null. А в этом случае, можно провести count непосредственно по этому полю:
Реализация:
Вместо обычного кода:
Замечание:
Если запрос строится на Criteria API, то существует баг, воспроизводимый при попытке count-запроса для сущности с составным первичным ключом (composite primary key).
Ошибка при этом звучит так:
Caused by: java.sql.SQLException: ORA-00907: missing right parenthesis
Причина:
Запрос формируется в таком виде:
select count((field1, field2)) from MyEntity;
Дело в том, что Hibernate сам ищет идентификаторы сущности и подставляет в count их, а не wildcard (*).
Изучение жалоб говорит о том, что полученный запрос не воспринимается oracle, mysql, зато выполняется в mssql.
Есть также и открытый дефект на трекере Hibernat'а: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5419
Впрочем, он открыт уже почти год. А потому быстрее найти способ обойти проблему, чем ждать централизованного решения.
Решение:
На полноценное решение не тянет, но, уверен, поможет 95% столкнувшихся с проблемой.
Как правило составной идентификатор состоит из нескольких внешних ключей. И наверняка хоть один из них not null. А в этом случае, можно провести count непосредственно по этому полю:
select count(pk1) from MyEntity;
Реализация:
Вместо обычного кода:
CriteriaQuery<Long> query = getCriteriaBuilder().createQuery(Long.class); Root<MyEntity> from = query.from(MyEntity.class); query.select(getCriteriaBuilder().count(from));пишем следующий:
CriteriaQuery<Long> query = getCriteriaBuilder().createQuery(Long.class); Root<MyEntity> from = query.from(MyEntity.class); query.select(getCriteriaBuilder().count(from.get(MyEntity_.field1)));
Замечание:
select count(field) from tableВозвращает количество кортежей (строк) таблицы, в которых field is not null, при этом совпадения значений field у кортежей ни на что не влияют.
Комментариев нет:
Отправить комментарий