JPA:将SQL查询转换为JPA查询

时间:2014-04-09 17:01:01

标签: sql hibernate jpa

如何将以下查询转换为JPA查询:

  select * from (select * from t1 where id=14 order by timestamp desc) as h group by hnumber order by timestamp desc limit 0, 15

我尝试过像下面这样做,但语法错误失败了。

  select m from (select n from t1 n where n.id=:id order by timestamp desc) as m group by hnumber order by timestamp desc limit 0, 15

请纠正我,基本上我需要按时间戳的降序获取不同的记录。任何帮助表示赞赏。

更新: t1表中的列是:

  seq
  id
  message
  timestamp
  hnumber

基本上我需要按时间戳的降序为id(id就像用户)和hnumber(可以是多个)获取不同的行。 id和hnumber中的时间戳应该更大。

请注意:插入t1表的顺序可能不是时间戳的顺序。每个ID都可以有不同的消息。

更新2:

以下是一个例子:

    Seq     id  message timestamp       hnumber
    1001    14  xyz1    1394607463000   0429c3866c19981fc276855ff3cdaf100e0c9fdb
    1002    14  xyz2    1394608378000   0429c3866c19981fc276855ff3cdaf100e0c9fdb
    1003    14  xyz1    1394453678000   0429c3866c19981fc276855ff3cdaf100e0c9fdb
    1004    14  xyz2    1394608520000   0429c3866c19981fc276855ff3cdaf100e0c9fdb
    1005    14  xyz9    1394612791000   369d7cf7bd90fac78ef635b188e2a9952d77a8d1
    1006    14  xyz7    1394608513793   0429c3866c19981fc276855ff3cdaf100e0c9fdb
    1008    14  xyz6    1394608513793   0429c3866c19981fc276855ff3cdaf100e0c9fdb
    1009    14  xyz3    1394622221000   369d7cf7bd90fac78ef635b188e2a9952d77a8d1
    1010    14  xyz4    1394608513793   369d7cf7bd90fac78ef635b188e2a9952d77a8d1

我期待的输出:

    Seq     id  message timestamp       hnumber
    1009    14  xyz3    1394622221000   369d7cf7bd90fac78ef635b188e2a9952d77a8d1
    1004    14  xyz2    1394608520000   0429c3866c19981fc276855ff3cdaf100e0c9fdb

2 个答案:

答案 0 :(得分:0)

此查询存在多处错误,例如LIMIT是MySQL特定的语法。您可以改用query.setFirstResult(0)query.setMaxResults(15)

但更大的问题是子查询仅在SELECT和WHERE子句中受支持,而不在FROM中。请参阅here

您可能需要考虑使用上面的纯SQL版本并将其传递给createSqlQuery(String)(或createNativeQuery(String)如果您正在使用EntityManager API)。

请注意,这些本机SQL查询不能移植到不同的RDBMS。

答案 1 :(得分:0)

您可以将其写为HQL相关子查询,以避免在from子句中使用连接。例如以下查询将返回给定id

的每个hnumber的最新消息
select um.id,um.hnumber,um.message from UserMessage as um 
  where um.timestamp in (
    select max(timestamp) from UserMessage um1 
      where um1.id=:id and um1.hnumber=um.hnumber group by id,hnumber
    )

您没有指定用于映射表T1的实体的名称,因此在上面,我已将其称为" UserMessage"。

获取整个表的结果的一般形式是:

select um.id,um.hnumber,um.message from UserMessage as um 
  where um.timestamp in (
    select max(timestamp) from UserMessage um1 
      where um1.id=um.id and um1.hnumber=um.hnumber group by id,hnumber
    )

你可以看到内部子查询是一个相关的子查询,因为它引用了外部查询中的元素 - um.id和um.hnumber。

我在github上放了一个这个查询的工作示例:

https://github.com/hedleyproctor/hibernate-mapping-and-query-examples

如果您查看Tests类,您将看到一个名为" hqlWithCorrelatedSubquery"的测试。它使用上面的示例数据,并将输出显示为:

Printing results for query against entire table:
14
0429c3866c19981fc276855ff3cdaf100e0c9fdb
1394608520000
xyz2
14
369d7cf7bd90fac78ef635b188e2a9952d77a8d1
1394622221000
xyz3

作为一般规则,许多涉及from子句中的连接的简单SQL表达式可以重写为相关子查询,以允许它们转换为HQL或Hibernate Criteria查询。理论上,如果相关子查询在一个范围内执行,则相关子查询可能会很慢,因为与连接不同,相关子查询应该"对外部结果集中的每一行重复进行评估,但实际上,许多数据库查询优化器将以与等效连接查询相同的方式处理它,方法是在单个操作中将内部查询结果创建为查找表,因此性能将是完全相同的。

相关问题