OpenJPA与众不同

时间:2014-06-23 08:39:42

标签: java postgresql openjpa

在我的数据库架构中,我与几封电子邮件进行了对话。我想从对话列表中获取最新的电子邮件。在PostgreSql中查询:

select distinct on (conversation_id) * 
from email 
where conversation_id in (7085214, 7084964) 
order by conversation_id, processing_date desc

OpenJPA的:

(List<Email>) entityManager.createQuery("SELECT
   distinct(email.conversation.id), email FROM Email email WHERE
      email.conversation.id in :id ORDER BY email.conversation.id,
      email.processingDate DESC").setParameter("id", conversationIds);

它会在会话中返回会话ID和整个电子邮件列表的地图。

我怎么能做对吗?

由于

1 个答案:

答案 0 :(得分:0)

使用本机SQL。

实现所需功能的唯一方法是为OpenJPA开发一个补丁,“教会”它如何在其JPQL解析器和查询生成器中使用PostgreSQL扩展DISTINCT ON。大多数ORM通过方言挂钩接受此类扩展。不要指望这是一项简单的任务 - 除非您正在编写这些查询的批次,否则本机SQL几乎肯定会更容易。

您不能只使用DISTINCTDISTINCT ON之类的功能。他们不是;它们是完全独立的语法。 JPQL引擎会尝试将其转换为在运行时失败的真正函数调用 - 或者在distinct on的情况下,只是无法在第一时间解析它。

BTW,DISTINCT ON有点像GROUP BY在某些其他供应商数据库(如MySQL)中,您可以在SELECT中指定未出现在GROUP BY中的列{1}}或聚合。所以在MySQL中人们可能只是通过生成一个MySQL接受的技术上无效的查询来做到这一点 - 很可能OpenJPA JPQL处理程序不会注意到这个问题,所以它会通过它来完成它。这个技巧不适用于DISTINCT ON,而PostgreSQL严格遵守GROUP BY的标准,它不会让您使用GROUP BY生成非确定性查询。