JPQL 在 Select 语句中创建新对象 - 避免还是接受?

Posted

技术标签:

【中文标题】JPQL 在 Select 语句中创建新对象 - 避免还是接受?【英文标题】:JPQL Create new Object In Select Statement - avoid or embrace? 【发布时间】:2011-01-22 06:43:41 【问题描述】:

我最近了解到,可以在JPQL 语句中创建新对象,如下所示:

select new Family(mother, mate, offspr)
from DomesticCat as mother
    join mother.mate as mate
    left join mother.kittens as offspr

这是应该避免还是应该接受的事情?根据良好做法,何时使用此功能是合理的?

【问题讨论】:

【参考方案1】:

不要回避,SELECT NEW 之所以存在,是因为§10.2.7.2 中提醒过它有完全有效的用例。 EJB 3.0 JPA Specification 的 SELECT 子句中的 JPQL 构造函数表达式

构造函数可以用于 SELECT 列表返回一个或多个 Java 实例。指定的类不是 必须是实体或 映射到数据库。 该 构造函数名称必须是完整的 合格。

如果指定了实体类名 在 SELECT NEW 子句中, 生成的实体实例在 新状态。

SELECT NEW com.acme.example.CustomerDetails(c.id, c.status, o.count)
FROM Customer c JOIN c.orders o
WHERE o.count > 100

简而言之,当您不想以类型安全的方式(而不是Object[])检索完整实体或对象的完整图时,请使用 SELECT NEW。将查询结果映射到实体类还是非映射类将取决于您的选择。一个典型的例子是列表屏幕(您可能不需要所有详细信息)。

换句话说,不要到处使用它,但不要禁止它使用(很少有东西只有黑色或白色)。

【讨论】:

我想做同样的事情,但在我的查询中我有一些 join fetch 和 jpa 抱怨:query specified join fetching, but the owner of the fetched association was not present in the select list。伤心... 请编辑您的答案并将“构造函数名称必须完全限定”加粗。它非常重要,也是常见的错误来源。 答案完全正确,但链接的文档与答案不匹配。应该是jcp.org/aboutJava/communityprocess/final/jsr317/index.html 如果您使用的是static 嵌套类,请使用$,例如SELECT NEW org.soluvas.sanad.core.QuranManager$QuranChapterSummary(c.chapterNum, c.name, c.verseCount) FROM QuranChapter c @Woland 因为查询作为字符串传递给 hibernate/jpa 并且 JPA 不知道查询中的哪个类。你的项目中可以有 10 个 CustomerDetails 类。这就是你告诉 hibernate/jpa 使用哪一个的方式。【参考方案2】:

当您想要检索数据传输对象时,您经常使用这种查询。也许报告可能是使用它的好地方。如果您只想检索单个域对象(例如 from Family),那么没有理由使用它。

【讨论】:

好点,但您认为 Repository 应该返回 DTO 而不是实体吗?我正在正常转换Service层中的对象,在Repository中是不是太早了?【参考方案3】:

使用 new 创建的 Object 不必是 DTO,即将由业务层导出的 Object。也可以是 POJO Domain Object,即业务层内部使用的 Object。

使用这种 POJO 作为部分对象而不是完整的 JPA 实体的原因是在特定类型的 JOINS 中的性能。一个很好的资源可以解释这一点:http://use-the-index-luke.com/sql/join/hash-join-partial-objects

【讨论】:

以上是关于JPQL 在 Select 语句中创建新对象 - 避免还是接受?的主要内容,如果未能解决你的问题,请参考以下文章

SQL初级SQL简介语法SELECT语句SELECT DISTINCT语句

SQL初级SQL简介语法SELECT语句SELECT DISTINCT语句

JPQL 和元组列表作为 SELECT IN 语句的参数

Sonata Admin:无法在产品中创建新对象

如何在具有角度注入参数的打字稿中创建新对象

在JNI中创建新对象