在我的 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 检索所需的数据?
最佳答案
hibernate 的目标是将数据库实体映射到 java 对象。这种复杂的查询本身并不是实体。这违背了hibernate的精神。
如果此查询在您的应用程序逻辑中生成一个实体,我建议将结果放入表中并将 Hibernate 查询应用于该表。
如果此查询生成某种聚合或摘要,则有两种可能的方式:
一种方法是在使用 hibernate 从
iostatus
表中检索实体后,在您的应用程序中计算此聚合/摘要。如果此查询与您的应用程序逻辑无关,那么您可以使用 Native SQL interface Hibernate 并直接执行查询。 (如果您愿意操作两个数据库连接,您甚至可以使用 JPA。)
如果一定要转成HQL,就需要去掉partition函数。如果 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,但我不确定。
顺便说一下,我必须警告您,这些方法可能不会比在您的应用程序中查找更改执行得更好,因为它们涉及将表连接到自身,这是一项昂贵的操作;并且第二个查询涉及连接后的嵌套查询,这也是相当昂贵的。
关于java - 将 Postgresql 查询转换为 Hibernate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22095854/