在我的Java Web应用程序中,我使用Postgresql,并且一些数据表在服务器中自动填充。在数据库中,我有一个STATUS表,如下所示:
我想在所选日期和车辆保持连接的位置之间选择与车辆相关的数据。简单地说,我想在上表中选择绿色的数据,这意味着我在第一次io1 = true时确切地想要数据,而在最后一次io1 = true之后io1 = false时的数据。我有postgresql查询语句,它确切地给了我所需的数据;但是,由于我的应用程序逻辑,我必须将其转换为HQL。
工作postgresql查询:
WITH cte AS
( SELECT iostatusid, mtstrackid, io1,io2,io3, gpsdate,
(io1 <> LAG(io1) OVER (PARTITION BY mtstrackid
ORDER BY gpsdate)
) AS status_changed
FROM iostatus
WHERE mtstrackid = 'redcar' AND gpsdate between '2014-02-28 00:00:00' and '2014-02-28 23:59:59'
)
SELECT iostatusId, mtstrackid, io1, io2, io3,gpsdate
FROM cte
WHERE status_changed
OR io1 AND status_changed IS NULL
ORDER BY gpsdate ;
我应该如何将上述查询转换为HQL,或者如何使用HQL检索所需的数据?
答案 0 :(得分:0)
hibernate的目标是将数据库实体映射到java对象。这种复杂的查询本身不是实体。这违背了冬眠的精神。
如果此查询在您的应用程序逻辑中生成实体,我建议将结果放入表中并将Hibernate查询应用于该表。
如果此查询生成某种聚合或摘要,则有两种可能的方法:
一种方法是在使用hibernate从iostatus
表中检索实体后,在应用程序中计算此聚合/摘要。
如果此查询与您的应用程序逻辑无关,那么您可以使用Hibernate的Native SQL interface并直接执行查询。 (如果您愿意操纵两个数据库连接,甚至可以使用JPA。)
如果您绝对需要将其转换为HQL,则需要消除分区功能。如果iostatusId
的顺序与gpsdate
的顺序相同,则可以类似于
SELECT i2.*
FROM iostatus i1
INNER JOIN iostatus i2 ON i1.iostatusId = i2.iostatusId - 1
AND i1.io1 <> i2.io1
AND i1.mstrackid = i2.mstrackid
WHERE i2.mtstrackid = 'redcar' AND
i2.gpsdate between '2014-02-28 00:00:00' and '2014-02-28 23:59:59'
如果gpsdate
与iostatusId
无关,那么您需要
SELECT i2.*
FROM iostatus i1
INNER JOIN iostatus i2 ON i1.gpsdate < i2.gpsdate
AND i1.io1 <> i2.io1
AND i1.mstrackid = i2.mstrackid
WHERE i2.mtstrackid = 'redcar' AND
i2.gpsdate between '2014-02-28 00:00:00' and '2014-02-28 23:59:59' AND
NOT EXISTS (SELECT * FROM iostatus i3
WHERE i3.gpsdate > i1.gpsdate AND
i2.gpsdate > i3.gpsdate AND
i3.io1 = i1.io1 AND
i1.mstrackid = i3.mstrackid)
我想这两个查询都可以转换为HQL,但我不确定。
顺便说一句,我必须警告你,这些方法可能不会比你在应用程序中找到更改更好,因为它们涉及将表连接到自身,这是一项昂贵的操作;第二个查询涉及连接后的嵌套查询,这也非常昂贵。