JPQL在Select语句中创建新对象 - 避免或拥抱?

mga*_*mer 60 java orm hibernate jpa jpql

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

select new Family(mother, mate, offspr)
from DomesticCat as mother
    join mother.mate as mate
    left join mother.kittens as offspr
Run Code Online (Sandbox Code Playgroud)

这是要避免还是要拥抱?根据良好做法,何时使用此功能是合理的?

Pas*_*ent 115

不要避免它,SELECT NEW就在那里,因为在§10.2.7.2中提醒它有完全有效的用例.EJB 3.0 JPA规范的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
Run Code Online (Sandbox Code Playgroud)

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

换句话说,不要在任何地方使用它,但不要禁止它的使用(很少的东西只是黑色或白色).

  • 如果您使用的是`static`嵌套类,请使用`$`,例如`SELECT NEW org.soluvas.sanad.core.QuranManager $ QuranChapterSummary(c.chapterNum,c.name,c.verseCount)FROM QuranChapter c` (10认同)

Art*_*ald 30

当您想要检索数据传输对象时,通常会使用此类查询.也许报告可以是一个使用它的好地方.如果您只想检索单个域对象(例如来自Family),那么没有理由使用它.

  • 提及DTO的+1 - 完全是我的用例 (3认同)
  • 很好,但是您认为存储库应该返回DTO而不是实体吗?我通常在Service层中转换对象,在Repository中还不是太早? (2认同)

小智 7

使用new创建的对象不必是DTO,即将由Business层导出的Object.它也可以是POJO域对象,即Business层内部使用的Object.

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