【问题标题】:Convert Postgresql query to Hibernate将 Postgresql 查询转换为 Hibernate
【发布时间】:2014-04-01 11:54:23
【问题描述】:

在我的 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 检索所需的数据?

【问题讨论】:

  • 您可以使用本机查询调用数据库。然后你可以使用上面的代码。我怀疑这里的任何人都会将其翻译成 HQL,如果您提供了足够的信息也是值得怀疑的。
  • ClassCastException.
  • 我不认为 HQL 支持通用表表达式甚至窗口函数。它只支持最基本的SQL语句。
  • 那么,我怎样才能检索到所需的数据呢?你有什么建议吗?谢谢

标签: java hibernate postgresql


【解决方案1】:

hibernate 的目标是将数据库实体映射到 java 对象。这种复杂的查询本身并不是实体。这违背了冬眠的精神。

如果此查询在您的应用程序逻辑中生成实体,我建议将结果放入表中并将 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'

如果gpsdateiostatusId 没有任何关系,那么您需要类似

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,但我不确定。

顺便说一句,我必须警告您,这些方法可能不会比在您的应用程序中查找更改更好,因为它们涉及将表连接到自身,这是一项昂贵的操作;而第二个查询涉及到join后的嵌套查询,开销也很大。

【讨论】:

  • 我编辑了我的问题。在我的应用程序逻辑中,上面的查询用我想要的数据总结了 iostatus 表。但是,我必须将其转换为 HQL 查询。如果我从表中检索所有数据后汇总数据,因为数据量很大,所以会出现性价比问题。
  • 我还是不明白你的表架构和查询完美。但是,如果您绝对需要用 HQL 编写此查询,则需要对其进行重构。您不能在 HQL 中使用 CTE 和窗口分区。这些东西并非对每个数据库供应商都可用,并且 HQL 独立于供应商。消除 CTE 很容易,使用嵌套查询。 CTE 只是语法糖。而且我想您可以轻松消除窗口分区。实际上,由于 mstrackid 上的 where 子句,您似乎没有使用分区。
  • 我在我的问题中详细解释了所有内容。你能看一下吗?
  • 因此,如果这种方式很昂贵,最好不要以这种方式检索数据。我应该用所需的条件检索数据,然后我应该检查它并提取我需要的东西。这种方法比我上面解释的方法更好吗?谢谢。
  • 这取决于您的应用程序的详细信息。如果您有数十亿条记录,或者如果您在数据库和应用程序服务器之间的带宽较低,您将不希望移动大量数据。如果您的数据库负载很重,您可能不想在服务器上进行太多计算。
猜你喜欢
  • 2017-03-24
  • 2015-10-10
  • 2018-12-08
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 2023-02-01
相关资源
最近更新 更多