1

我正在尝试使用 QueryDsl 调用 SQL 语句,Spring Data JPA 无法涵盖该语句。这是我要运行的句子。

SELECT timestamp, deviceId 
  FROM EventData a
INNER JOIN
(SELECT max(timestamp) timestamp, deviceId 
   FROM EventData 
  GROUP BY deviceId) b
USING (timestamp,deviceId)
WHERE deviceId in ('1', '2')

我确实喜欢下面:

@PersistenceContext
EntityManager em;

JPAQuery query = new JPAQuery(em);
QEventData eventData = new QEventData();

return
query.from(eventData)
     .innerJoin(
               query.from(eventData)
                    .groupBy(eventData.deviceId)
                    .list(eventData.deviceId, eventData.timestamp.max())
      ).on(eventData.deviceId.eq(?))
.where(eventData.deviceId.in("1", "2"))
.list(eventData);

我不知道我为 innerJoin 放了什么。我尝试了 QueryDsl 示例,但找不到正确的示例。我在哪里可以获得 QueryDsl 的好例子?

谢谢,您的回答将不胜感激。

4

1 回答 1

1

这只是部分答案,但它在 JUnit 测试中对我有用。我使用 SQL 查询,而不是 JPA。值得一试:

    Connection connection = getConnection();
    SQLTemplates dialect = new PostgresTemplates(); // TODO: use appropriate db template
    QEventData c = new QEventData("c");
    QEventData c2 = new QEventData("c2");

    // Use this to hold alias for inner select
    PathBuilder<Object[]> c2alias = new PathBuilder<Object[]>(Object[].class, "c2alias");

    SQLQuery query =  new SQLQuery(connection , dialect);
    return query.from(c).innerJoin(
           new SQLSubQuery().from(c2)
                .groupBy(c2.deviceid)
                .list(c2.device, c2.timestamp.max().as("timestamp")), c2alias
    ).on(c.deviceid.eq(c2alias.get("deviceid")),
        c.timestamp.eq(c2alias.get("timestamp")))
    .where(c.deviceid.in(1, 2))
            .list(c.deviceid, c.timestamp);

注意 1:在 list() 函数中,您必须明确列出要选择的字段,否则会出现错误,我认为这是由于使用了 PathBuilder 内部选择别名。

注意 2:其他帖子表明这可能不适用于 JPA,仅适用于 SQL:https ://groups.google.com/forum/#!msg/querydsl/WDX6oB7Ivsg/0fzoLJA35lgJ

注 3:在我写的那么多 SQL 中,我还没有看到在实践中使用过 USING 子句,对于那些不知道的人:http: //docs.oracle.com/javadb/10.8.1.2/ref/ rrefsqljusing.html

注意 4:如果上述方法不适用于 querydsl/JPA,则考虑重构查询以使用 EXISTS 子句。

于 2013-10-17T14:01:23.293 回答