JPA2 Criteria API создает недопустимый SQL при использовании groupBy

JPA2 с Criteria API, похоже, генерирует недопустимый SQL для PostgreSQL. Для этого кода:

Root<DBObjectAccessCounter> from = query.from(DBObjectAccessCounter.class);
Path<DBObject> object = from.get(DBObjectAccessCounter_.object);
Expression<Long> sum = builder.sumAsLong(from.get(DBObjectAccessCounter_.count));
query.multiselect(object, sum).groupBy(object);

Я получаю следующее исключение:

ERROR: column "dbobject1_.id" must appear in the GROUP BY
clause or be used in an aggregate function

Сгенерированный SQL:

select dbobjectac0_.object_id as col_0_0_,
    sum(dbobjectac0_.count) as col_1_0_, dbobject1_.id as id1001_,
    dbobject1_.name as name1013_,
    dbobject1_.lastChanged as lastChan2_1013_,
    dbobject1_.type_id as type3_1013_
    from DBObjectAccessCounter dbobjectac0_
    inner join DBObject dbobject1_
    on dbobjectac0_.object_id=dbobject1_.id
    group by dbobjectac0_.object_id

Очевидно, что первый элемент оператора select (dbobjectac0_.object_id) не соответствует предложению group by.

Упрощенный пример

Это даже не работает для этого простого примера:

Root<DBObjectAccessCounter> from = query.from(DBObjectAccessCounter.class);
Path<DBObject> object = from.get(DBObjectAccessCounter_.object);
query.select(object).groupBy(object);

который возвращает

select dbobject1_.id as id924_, dbobject1_.name as name933_,
    dbobject1_.lastChanged as lastChan2_933_,
    dbobject1_.type_id as type3_933_
    from DBObjectAccessCounter dbobjectac0_
    inner join DBObject dbobject1_
    on dbobjectac0_.object_id=dbobject1_.id
    group by dbobjectac0_.object_id

и выдает ту же ошибку, что и выше.

Группировка по идентификатору вместо типа

Группировка по идентификатору в соответствии с сообщением об ошибке с

Root<DBObjectAccessCounter> from = query.from(DBObjectAccessCounter.class);
Path<DBObject> object = from.get(DBObjectAccessCounter_.object);
Path<Long> objectId = from.get(DBObjectAccessCounter_.object).get(DBObject_.id);
query.select(object).groupBy(objectId);

также приводит к той же ошибке.

Кто-нибудь знает, как это исправить?


person Stephan Windmüller    schedule 13.09.2012    source источник
comment
Разве вы не должны использовать object.id в предложении groupBy? Означает ли groupBy(object) неявно группу по первичному ключу в JPA? Или группировать по всем полям? Можете ли вы показать ошибку, вызванную упрощенным примером?   -  person Craig Ringer    schedule 14.09.2012
comment
Я добавил пример с группировкой по идентификатору объекта, который приводит к той же ошибке. Это сообщение об ошибке появляется во всех упомянутых примерах.   -  person Stephan Windmüller    schedule 14.09.2012


Ответы (2)


В PostgreSQL 9.2 и более поздних версиях улучшен способ обнаружения «неявно сгруппированных» столбцов, т. е. места, где вы поместили первичный ключ в group by, чтобы все поля из этой таблицы могли быть указаны в списке SELECT. Предыдущие версии не обнаруживали этого, поэтому SELECT id, somefield FROM sometable GROUP BY id приводило к Column sometable.somefield must appear in the GROUP BY clause. В более новых версиях Pg обнаружит, что somefield неявно сгруппировано, поскольку id включено, и разрешит выполнение этого запроса.

К сожалению, я не уверен, что это решит вашу проблему; ваша проблема в том, что вы группируете по ключу на другой стороне условия соединения, где я сомневаюсь, что Pg распознает его как ПК, поскольку этот столбец не помечен как таковой.

Я предлагаю вам написать автономный тестовый пример и отправить отчет о проблеме в Hibernate JIRA. Ссылка на него здесь; как только будет полный и работоспособный тестовый пример, я поиграю и посмотрю.

Кроме того, вы уверены, что сообщение об ошибке остается точно таким же в вашем измененном тестовом примере, оно не относится к псевдониму с другим номером или чему-то еще?

person Craig Ringer    schedule 16.09.2012
comment
Спасибо за вашу помощь! Я создал JIRA с необходимым тестовым примером: hibernate.onjira.com/browse/JPA-34< /а> - person Stephan Windmüller; 17.09.2012
comment
@ Стефан Я не знаю, можете ли вы изменить его сейчас, когда вы его подали, но на самом деле он должен быть подан под HIBERNATE, а не JPA. Проект JPA предназначен для спецификации. - person Craig Ringer; 18.09.2012
comment
@Stephan Когда вы посмотрите это, проголосуйте за него тоже. Кстати, преобразовал тестовый пример в EclipseLink, и два более простых теста проходят, но testGroupByWithSum тоже не проходит. Я не уверен, что testGroupByWithSum правильно. Можете ли вы DL преобразовать тест EclipseLink и поиграть с ним, посмотреть, сможете ли вы заставить testGroupByWithSum работать? - person Craig Ringer; 18.09.2012
comment
Я переместил отчет об ошибке в HHH. Должен ли ваш новый указываться как дубликат? - person Stephan Windmüller; 18.09.2012
comment
@Stephan Не был уверен, сможешь ли ты это сделать, поэтому я перепрошил. По-видимому, я не могу закрыть или удалить свою собственную задачу JIRA (грр!), но я пометил ее как дубликат. Извините, я забыл, как мало JIRA позволяет вам делать. - person Craig Ringer; 18.09.2012

Я протестировал ваш первый пример на EclipseLink и MySql. Он не выдает никаких исключений, и, если я правильно понял вашу цель, результирующий запрос — это то, что вы ищете:

SELECT t0.id, t0.name, SUM(t1.count) 
FROM dbobject t0, dbobjectaccesscounter t1 
WHERE (t0.id = t1.object_id) GROUP BY t0.id, t0.name
person perissf    schedule 14.09.2012