- Published on
Return Custom Object from JPQL query. JPQL Constructor Expression And Projection
- Authors
- Name
- Sunil Kanzar
- @SunilKanzar
Overview
When anyone thinks about returning a custom object from the JPA repository, they're most probably thinking about Projection and I agree that is a preferable way to do so, But there is another way too to archive the same.
You can archive this by using JPQL Constructor Expression in JPQL query.
Note: JPQL Constructor Expression will only work with JPQL query not in a native query.
Let's start with example first:
Create Bean class (POJO)
Let's say we have Author entity with us
@Table(name = "authors")
@Entity
class Author {
@Id
@GeneratedValue
private Long id;
private String name;
private Integer age;
private String qualification;
}
from which we just want to return some fields or may be aggregation of some fields.
Let's take an example of grouping author by age
and find count of same age author. In that case, we need to create a Bean class like follow
class AgeCount {
private Integer age;
private Long count;
public AgeCount(Integer age, Long count) {
this.age = age;
this.count = count;
}
}
Write repository and method that return above Bean
public interface AuthorRepository extends JpaRepository<Author, Long> {
@Query("select new com.demo.api.view.AgeCount(age, count(id)) from Author group by age")
List<PublicAuthorView> getAgeCount();
}
Here comes the list of Important things
- Make sure that you write fully qualified name of Bean or POJO class. Like :
com.demo.api.view.AgeCount
- Make sure you put
new
keyword before constructor call. Like :... new com.demo.api.view.AgeCount(age, count(id)) ...
- Make sure you pass argument in same order and type as it in constructor or else it will give you and exception at runtime, or it might provide you the unexpected values.
- Take a note that it will only work with non-native (JPQL) query for the native query you need to use Projection.
If you see closely first three points are just mansions that you need to call constructor but with fully qualify name.