Hibernate:未正确计算条件查询

时间:2011-07-06 11:40:37

标签: java hibernate ejbql

我正在尝试让以下查询在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"

没有自联接的同一查询不起作用。看似多余的括号也是如此。使用它们,它返回不正确的结果。

所以现在我的问题是,为什么有必要以这种方式构造查询,无论是关于自连接还是“多余”括号?

值得注意的是,obj1obj2是同一外国实体的不同实例。所以我查询的表在一个外表中引用了两个不同的行。我怀疑这就是为什么自我加入是必要的(这就是我决定尝试自我加入的原因),但我不确定它背后的原因是什么。任何解释都会受到欢迎。

2 个答案:

答案 0 :(得分:1)

在检查时看起来没问题......您可以尝试这种详细的方法:

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

答案 1 :(得分: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

我感谢Randy提出的非常好的建议,但在我的具体情况下,它不起作用,我不得不使用自联接重写我的原始查询以获得正确的结果。