Hibernate: условный запрос не оценивается правильно - PullRequest
1 голос
/ 06 июля 2011

Я пытаюсь заставить следующий запрос работать в Hibernate:

SELECT m FROM MyEntity m WHERE m.owner = :user 
                         AND m.field1 IN (:field1Vals) 
                         AND m.field2 IN (:field2Vals) 
                         AND m.obj1 IS NOT NULL 
                         AND (
                                 m.obj1.count > 0
                             OR 
                                 (m.obj2 IS NOT NULL 
                                  AND m.obj2.count > 0)
                             ) 
                         ORDER BY m.createDate DESC

Проблема, кажется, всегда оценивает часть, которая идет:

AND (
        m.obj1.count > 0
    OR 
        (m.obj2 IS NOT NULL 
         AND m.obj2.count > 0)
)

... как:

AND (m.obj2 IS NOT NULL 
     AND m.obj2.count > 0)

Другими словами, это только возврат объектов, которые удовлетворяют условию, которое следует за OR, и игнорирование любых результатов, которые удовлетворяют первому условию. Если я удаляю условие, следующее за OR, запрос корректно возвращает объекты, которые удовлетворяют условию m.obj1.count > 0.

Я предполагаю, что допустил некоторую базовую ошибку в том, как я структурировал свой запрос, но я не уверен, что это может быть. Есть идеи?

Обновление

Я нашел вариант, который работает, он использует самосоединение и добавляет лишние скобки:

SELECT DISTINCT m FROM MyEntity m, MyEntity m2 WHERE m.owner = :user 
                                               AND m.field1 IN (:field1Vals) 
                                               AND m.field2 in (:field2Vals) 
                                               AND m.obj1 IS NOT NULL 
                                               AND (
                                                       (m.obj1.count > 0) 
                                                   OR 
                                                       (m2.obj2 IS NOT NULL 
                                                        AND (m2.obj2.count > 0))
                                                   ) 
                                               ORDER BY m.createDate DESC"

Этот же запрос без самостоятельного объединения не работает. То же самое касается, казалось бы, лишних скобок. С ними он возвращает неверный результат.

Итак, теперь мой вопрос: почему необходимо структурировать запрос таким образом, как в отношении самосоединения, так и «лишних» скобок?

Возможно, стоит отметить, что obj1 и obj2 - это разные экземпляры одного и того же иностранного лица. Таким образом, таблица, к которой я обращаюсь, ссылается на две разные строки в одной внешней таблице. Я подозреваю, что это было причиной, по которой было необходимо самосоединение (и именно поэтому я решил попробовать самосоединение), но я точно не знаю, в чем причина этого. Любое объяснение будет приветствоваться.

Ответы [ 2 ]

1 голос
/ 06 июля 2011

выглядит хорошо при осмотре ... вы можете попробовать этот подробный метод:

SELECT m FROM MyEntity m WHERE m.owner = :user 
                         AND m.field1 IN (:field1Vals) 
                         AND m.field2 IN (:field2Vals) 
                         AND m.obj1 IS NOT NULL 
                         AND (
                                 m.obj1.count > 0
                             ) 
union
SELECT m FROM MyEntity m WHERE m.owner = :user 
                         AND m.field1 IN (:field1Vals) 
                         AND m.field2 IN (:field2Vals) 
                         AND m.obj1 IS NOT NULL 
                         AND      (m.obj2 IS NOT NULL 
                                  AND m.obj2.count > 0)
ORDER BY m.createDate DESC
0 голосов
/ 10 июля 2011

Чтобы обойти эту проблему, мне пришлось пересмотреть мой запрос следующим образом:

SELECT DISTINCT m FROM MyEntity m, MyEntity m2 WHERE m.owner = :user 
                                               AND m.field1 IN (:field1Vals) 
                                               AND m.field2 in (:field2Vals) 
                                               AND m.obj1 IS NOT NULL 
                                               AND (
                                                       (m.obj1.count > 0) 
                                                   OR 
                                                       (m2.obj2 IS NOT NULL 
                                                        AND (m2.obj2.count > 0))
                                                   ) 
                                               ORDER BY m.createDate DESC

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

...