73

I've learnt recently that it is possible to create new Objects in JPQL statements as follows:

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

Is this something to be avoided or rather to embrace? When is usage of this feature justified in the light of good practices?

Hash
  • 4,647
  • 5
  • 21
  • 39
mgamer
  • 13,580
  • 25
  • 87
  • 145

3 Answers3

143

Don't avoid it, the SELECT NEW is there because there are perfectly valid use cases for it as reminded in the §10.2.7.2. JPQL Constructor Expressions in the SELECT Clause of the EJB 3.0 JPA Specification:

A constructor may be used in the SELECT list to return one or more Java instances. The specified class is not required to be an entity or to be mapped to the database. The constructor name must be fully qualified.

If an entity class name is specified in the SELECT NEW clause, the resulting entity instances are in the new state.

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

In short, use the SELECT NEW when you don't want to retrieve a full entity or a full graph of objects in a type safe way (as opposed to an Object[]). Whether you map the result of a query in an entity class or a non mapped class will depend on your select. A typical example would be a list screen (where you might not want all the details).

In other words, don't use it everywhere but don't forbid its use (few things are only black or white).

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 1
    I want to made the same thing but in my query I have some join fetch and jpa complains : `query specified join fetching, but the owner of the fetched association was not present in the select list`. Sad... – La Chamelle Mar 19 '12 at 13:49
  • 1
    Please edit your answer and make "The constructor name must be fully qualified" bold.. it is very important and a common source of errors. – Dominik Dorn Apr 18 '12 at 15:31
  • 1
    The answer is totally right, but the linked document doesn't match the answer. It should be http://jcp.org/aboutJava/communityprocess/final/jsr317/index.html – Pumuckline May 22 '12 at 16:35
  • 14
    If you're using a `static` nested class, use `$`, e.g. `SELECT NEW org.soluvas.sanad.core.QuranManager$QuranChapterSummary(c.chapterNum, c.name, c.verseCount) FROM QuranChapter c` – Hendy Irawan Aug 05 '14 at 07:58
  • @DominikDorn could you please clarify why full constructor name so important? What mistakes did you have in mind? – Woland Feb 27 '19 at 13:28
  • 1
    @Woland because the query is passed to hibernate/jpa as a string and JPA does not know which class is meant in the query. you could have 10 CustomerDetails classes in your project.. this is how you tell hibernate/jpa which one to use. – Dominik Dorn Feb 27 '19 at 17:07
  • In new object there are lot of parameters due to join queries result. Can we reduce those no of parameters in constructor ? – Avi Jan 05 '23 at 15:37
32

You often use this sort of query when you want to retrieve a Data Transfer Object. Maybe a report can be a good place to use it. If you just want to retrieve a single domain object (like from Family instead), so there is no reason to use it.

Hendy Irawan
  • 20,498
  • 11
  • 103
  • 114
Arthur Ronald
  • 33,349
  • 20
  • 110
  • 136
  • 2
    Good point, but do you think that Repository should return DTOs and not entities? I am converting the objects in Service layer normally, in Repository is not too early? – Mejmo Jul 03 '15 at 14:27
7

An Object created with new does not have to be a DTO, i.e. an Object which will be exported by the Business layer. It can also be a POJO Domain Object, i.e. an Object used internally by the Business layer.

The reason to use this kind of POJOs as a partial Object instead of the full JPA Entity is performance in specific kinds of JOINS. A great resource which explains this is: http://use-the-index-luke.com/sql/join/hash-join-partial-objects

gmournos
  • 91
  • 1
  • 3