自我加入Hibernate标准

时间:2015-02-02 04:31:37

标签: java sql hibernate sql-order-by hibernate-criteria

无法找到在此类伪搜索索引表上为条件添加顺序的方法:

----------------------------------
| id | person_id | field | value |
----------------------------------
| 1  | 1         | fname  | John |
| 2  | 1         | lname  | Smith|
| 3  | 1         | zip    | 3000 |
| 4  | 2         | fname  | John |
| 5  | 2         | lname  | Doe  |
| 6  | 2         | zip    | 3000 |
----------------------------------

search_index表是人员实体的索引,可以包含任意数量的任何类型的属性(当然,这是现实生活中的一个简单例子)。一个人#34;可以有fname设置,另一个可能没有等等。然后,客户端应用程序发送通用搜索请求,f.i。 ((fname = John OR fname = Karl)AND lname = Smith and zip = 3000) - 这种东西。所以系统是相当通用的 - search_index中的可搜索字段列表和任何类型的布尔搜索查询。 orderby也是如此 - 可以是任何可搜索的字段。

在SQL中我会做类似的事情:

SELECT si1.person_id from search_index si1
LEFT OUTER JOIN search_index si2 ON si1.id = si2.id
WHERE si2.field='lname'
AND si1.person_id in (select person_id from search_index where field = 'zip' and answer = '3000')
ORDER BY si2.value

按" lname"订购找到的结果。

可能使用HQL,但搜索标准是从搜索字符串动态构建的,与动态HQL构建相比,Hibernate Criteria API使其更容易。

1 个答案:

答案 0 :(得分:1)

  1. 为什么LEFT JOIN在同一个表中,然后在WHERE子句中使用JOINED表?这相当于INNER JOIN。

  2. 为什么在加入这两个表时还有一个额外的子选择。

  3. 为什么你甚至按照他们的ID加入两张桌子呢?在您的此查询中,您加入相同的行(因为您使用表ID作为连接条件)。

  4. 这个查询可以成为您想要的吗?

    SELECT si1.person_id 
    from search_index si1
    LEFT OUTER JOIN search_index si2 ON si1.person_id = si2.person_id AND si2.field='lname' 
    WHERE si1.field = 'zip' and si1.answer = '3000'
    ORDER BY si2.value
    

    HQL和Criteria查询只能在导航现有关联时帮助您(自连接不是这种情况)。所以在这种情况下你应该使用原生查询。

    现在,回到您的查询。您可以删除JOIN并将其写为:

    SELECT si1.person_id 
    from search_index si1
    WHERE si1.field='lname'
    AND si1.person_id in (select person_id from search_index where field = 'zip' and answer = '3000')
    ORDER BY si1.value
    

    在这种情况下,您可以编写HQL查询:

    select p.id
    from SearchIndex si
    join si.person p
    where 
       si.field = :field1 and
       p.id in (select si2.person.id from SearchIndex si2 where si2.field = : field2 and answer = :answer)
    order by si.value
    

    更新

    如果' lname'字段仅对订购有用,然后您需要将子查询移动到主查询中并移动' lname'在连接中:

    SELECT si1.person_id 
    from search_index si1
    where si1.field = 'zip' and si1.answer = '3000'
    LEFT OUTER JOIN search_index si2 ON si1.person_id = si2.person_id AND si2.field='lname' 
    ORDER BY si2.value
    

    由于自连接语法,这需要本机查询。

相关问题