使用HQL查询多对多联接表

时间:2013-05-01 12:38:32

标签: sql hibernate grails hql gorm

我需要一些建议来创建一个hql查询。

情况:我已设置Nodes,可为其分配可配置的Flags。为此,我有以下类/表:

课程:

class Node {
  String name
}

class Flag {
  String name
}

class NodeHasFlag {
  Node node
  Flag flag
  boolean value
}

包含一些示例数据的结果表:

Node
id, name
1,  'a'
2,  'b'
3,  'c'
...

Flag
id, name
1,  'visible'
2,  'special'
...

NodeHasFlag
node_id, flag_id, value
1,       1,       true      // node 'a' is visible
2,       1,       false     // node 'b' is not visible
2,       2,       true      // node 'b' is special
3,       1,       false     // node 'c' is not visible
...

现在我需要一个hql查询来获取基于标志的节点列表。

赞:向我提供visiblespecial

的所有节点

或者:给我visible的所有节点,special的值未定义(NodeHasFlag表中没有条目)

检查单个标志很容易,但同时检查多个标志会给我带来麻烦。

我正在使用Grails和Gorm,但我认为问题与标准Java Hibernate相同

2 个答案:

答案 0 :(得分:3)

我认为你可以用子查询来解决这个问题。第一个例子看起来像这样。第二个例子需要LEFT JOIN和OR IS NULL限制。

    select n from Node n
        where n.id in 
            (select n2.id from Node n2 
                join n2.flags f2 
                where f2.visible = :visibleValue)
       and n.id in
            (select n3.id from Node n3
                join n3.flags f3
                where f3.special = :specialValue)

答案 1 :(得分:1)

你也可以发挥创意(假设NodeHasFlag永远不会有相同的node_id和flag_id)并尝试这样的事情:

// Both visible and special
select n from Node n
   where 3 = (
     select SUM(CASE f.name WHEN 'visible' THEN 2 WHEN 'special' THEN 1 ELSE 0 END)
      from n.flags f))

// Visible but not special
select n from Node n
   where 2 = (
    select SUM(CASE f.name WHEN 'visible' THEN 2 WHEN 'special' THEN 1 ELSE 0 END)
      from n.flags f))

稍微优化但不太直观:)