JPQL Создать новый объект в операторе выбора - избегать или принимать?

Недавно я узнал, что можно создавать новые объекты в операторах JPQL следующим образом:

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

Этого следует избегать или, скорее, принять? Когда использование этой функции оправдано в свете передовой практики?


person mgamer    schedule 01.03.2010    source источник


Ответы (3)


Не избегайте этого, здесь есть SELECT NEW, потому что для него есть вполне допустимые варианты использования, как указано в §10.2.7.2. Выражения конструктора JPQL в предложении SELECT Спецификация EJB 3.0 JPA:

Конструктор может использоваться в списке 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

Короче говоря, используйте SELECT NEW, если вы не хотите извлекать полную сущность или полный граф объектов безопасным способом (в отличие от Object[]). От вашего выбора будет зависеть, отображаете ли вы результат запроса в классе сущности или в несопоставленном классе. Типичным примером может служить экран со списком (где вам могут не понадобиться все подробности).

Другими словами, не используйте его везде, но и не запрещайте его использование (некоторые вещи могут быть только черными или белыми).

person Pascal Thivent    schedule 01.03.2010
comment
Я хочу сделать то же самое, но в моем запросе есть несколько соединений, и jpa жалуется: query specified join fetching, but the owner of the fetched association was not present in the select list. Грустный... - person La Chamelle; 19.03.2012
comment
Пожалуйста, отредактируйте свой ответ и сделайте имя конструктора полностью определенным жирным шрифтом .. это очень важно и является частым источником ошибок. - person Dominik Dorn; 18.04.2012
comment
Ответ абсолютно правильный, но связанный документ не соответствует ответу. Это должно быть jcp.org/aboutJava/communityprocess/final/jsr317/index.html. - person Pumuckline; 22.05.2012
comment
Если вы используете static вложенный класс, используйте $, например SELECT NEW org.soluvas.sanad.core.QuranManager$QuranChapterSummary(c.chapterNum, c.name, c.verseCount) FROM QuranChapter c - person Hendy Irawan; 05.08.2014
comment
@DominikDorn, не могли бы вы пояснить, почему так важно полное имя конструктора? Какие ошибки вы имели в виду? - person Woland; 27.02.2019
comment
@Woland, потому что запрос передается в hibernate / jpa в виде строки, и JPA не знает, какой класс подразумевается в запросе. у вас может быть 10 классов CustomerDetails в вашем проекте ... вот как вы указываете hibernate / jpa, какой из них использовать. - person Dominik Dorn; 27.02.2019

Вы часто используете этот вид запросов, когда хотите получить объект передачи данных. Может быть, отчет может быть хорошим местом для его использования. Если вы просто хотите получить объект с одним доменом (например, из семейства), нет причин его использовать.

person Arthur Ronald    schedule 01.03.2010
comment
Хороший момент, но думаете ли вы, что репозиторий должен возвращать DTO, а не объекты? Я обычно конвертирую объекты в сервисном слое, в репозитории еще не рано? - person Mejmo; 03.07.2015

Объект, созданный с помощью new, не обязательно должен быть DTO, то есть объектом, который будет экспортирован бизнес-уровнем. Это также может быть объект домена POJO, то есть объект, используемый внутри бизнес-уровня.

Причина использования этого типа POJO в качестве частичного объекта вместо полной сущности JPA заключается в производительности в определенных типах JOINS. Вот отличный ресурс, который объясняет это: http://use-the-index-luke.com/sql/join/hash-join-partial-objects

person gmournos    schedule 04.04.2015