2013-05-01 138 views
0

我需要一些建议来创建一个hql查询。查询与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和格姆,但我认为这个问题将与标准的Java休眠

+0

问题是HQL不支持相交或联合。你可以做每个HQL语句,然后交叉列表。 – 2013-05-01 13:11:51

回答

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) 
+0

谢谢。我认为这可以帮助我:-) – micha 2013-05-03 18:39:53

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)) 

多一点优化,但少直观:)

+0

感谢这个想法,但我认为carbontax的approuch更可靠。 – micha 2013-05-03 18:42:46

+0

@Jim Sosa - 我个人对于这种创造性的方法有一个弱点,但是他们很难在现实生活中会对你的应用产生影响的情况下幸存下来。尽管如此,它很诱人。 :) – carbontax 2013-05-03 21:00:19