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语句