Запрос JPA 2, возвращающий неполные результаты

Следующий запрос соответствует только первому значению, найденному в подзапросе select, даже если все значения совпадают SELECT p FROM Profile p WHERE p.id IN (SELECT u.group FROM User u WHERE u.id = ?1)

Подзапрос возвращает список через запятую, например: 1,2,3, Запрос должен возвращать совпадения для всех трех результатов выбора подзапроса. Кто-нибудь знает, что может быть не так? Благодарю.

2 ответа

IN предложение не работает таким образом ни в JPQL, ни в SQL.

Значение внутри (..) это не строка, разделенная запятыми, это список значений. Этот список может быть указан буквально как строка, разделенная запятыми, или он может быть создан подзапросом, как в вашем случае. То есть условие в вашем запросе работает как p.id IN ("1,2,3") (скорее, чем p.id IN (1,2,3)), поэтому он не дает желаемого результата.

Таким образом, вы не можете использовать возможности языков запросов (JPQL или SQL) для написания запросов к денормализованной схеме (ваш столбец содержит список значений, поэтому он нарушает 1NF). Если у вас есть отношение многие ко многим между Profileс и Users, выразите это как отношение "многие ко многим" с промежуточной таблицей соединений.

В то время как IN оператор поддерживает сравнение с результатами подзапроса, то, что вы делаете, не может работать (и я удивлен, что вы даже получите один результат). Прежде чем идти дальше, позвольте мне процитировать спецификацию JPA 2.0:

4.6.9 В выражениях

Синтаксис использования оператора сравнения [NOT] IN в условном выражении выглядит следующим образом:

 in_expression:: =
    {state_field_path_expression | type_discriminator} [NOT] IN
        {(in_item {, in_item} *) | (подзапрос) | collection_valued_input_parameter }
in_item::= литерал | single_valued_input_parameter 

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

Значения литерала и / или входного параметра должны быть похожи на один и тот же тип абстрактной схемы для выражения state_field_path_expression в типе. (См. Раздел 4.12).

Результаты подзапроса должны быть похожи на тот же тип абстрактной схемы для выражения state_field_path_expression в типе. Подзапросы обсуждаются в разделе 4.6.16.

Примеры:

o.country IN (’UK’, ’US’, ’France’) верно для UK и ложь для Peru и эквивалентно выражению (o.country = ’UK’) OR (o.country = ’US’) OR (o.country = ’ France’),

o.country NOT IN (’UK’, ’US’, ’France’) ложно для UK и верно для Peru и эквивалентно выражению NOT ((o.country = ’UK’) OR (o.country = ’US’) OR (o.country = ’France’)),

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

Если значение выражения state_field_path_expression или in_item в выражении IN или NOT IN равно NULL или неизвестно, значение выражения неизвестно.

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

Итак, во-первых, p.id не соответствует возвращаемому типу подвыбора (что на самом деле является "второстепенной" проблемой).

Во-вторых, и это серьезная проблема и недоразумение, ваш запрос не приведет к чему-то вроде этого (с использованием "псевдокода"):

p.id IN (1, 2, 3) 

что вы хотели бы - но в

p.id IN (’1,2,3’) 

что, очевидно, не то, что вы хотите, и не будет работать.

Мой единственный совет: нормализуйте вашу базу данных.

Другие вопросы по тегам