JPA и JPQL: NoResultException при выборе из нескольких таблиц, где одно значение равно null

Я использую Java EE 6 и запрашиваю базу данных с помощью JPA javax.persistence.Entitymanager. У меня есть фрагмент кода запроса JPQL, который выглядит примерно так:

Query query = entityManager.createQuery("
    select A.propertyX, B.propertyY, C.propertyZ
    from TableA A, TableB B, TableC C
    where A.id = :id and B.id = A.id and C.type = B.type
");
query.setParameter("id", id);
Object[] result = (Object[]) query.getSingleResult();

Где propertyX / Y / X - это ссылки на другие сущности. В моем случае существует соответствующая строка из таблиц TableA, TableB и TableC. Для совпадающих строк TableA.propertyX и TableB.propertyY содержат значения, тогда как TableC.propertyZ имеет значение null (и не является обязательным).

Я ожидаю, что это выполнится и вернет массив Object [] со значениями для первых двух элементов (propertyX и propertyY) и null для третьего элемента (propertyZ).

Однако, когда свойствоZ имеет значение null, создается исключение NoResultException. Если я изменяю данные так, что свойство Z не равно нулю, запрос выполняется и возвращает значение.

  • Это ожидаемое поведение JPQL?
  • Как я могу гарантировать, что мой запрос будет вести себя так, как я ожидал?

Очевидный обходной путь - выбрать всю корневую сущность, а не любое подсвойство, например 'C', а не 'C.propertyZ', а затем получить свойство из объекта сущности. Однако я бы хотел, чтобы это работало так, как я ожидал, без этого.


person ola    schedule 03.11.2011    source источник


Ответы (1)


Если для данной строки в A и B есть строка в C, где C.type = B.type, но столбец propertyZ для этой строки имеет значение NULL, то вы правы, что ваш запрос должен возвращать запись.

Однако если для данной строки в A и B нет соответствующей строки в C, где C.type = B.type, то ваш запрос не вернет результата. Это не имеет ничего общего с JPQL, но с SQL

Если вы хотите, чтобы последний случай по-прежнему возвращал запись с нулевым значением в поле propertyZ, вам необходимо использовать ВНЕШНИЕ СОЕДИНЕНИЯ

HTH

person Bruno    schedule 03.11.2011
comment
Как я уже писал в своем вопросе: совпадают строки всех трех таблиц. Но если C.propertyZ имеет значение null, запрос не выполняется. Если C.propertyZ не null, запрос успешно что-то возвращает. Все остальное остается прежним. C.propertyZ не используется ни в одном из условий запроса. - person ola; 03.11.2011
comment
Не уверен, что могло быть причиной этого ... насколько фактический SQL-запрос отличается от этой упрощенной версии? Можете ли вы поделиться актуальным вопросом? - person Bruno; 04.11.2011
comment
Мой фактический запрос очень похож на тот, который используется здесь. Я даже изменил его, чтобы он выглядел так же, как здесь, и получил тот же результат. - person ola; 05.11.2011