Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Query returning Object instead of entity

When I use @Query annotation with select fields, I dont get the entity object back. How can I get the entity object back?

public interface CreditCenterRepository extends JpaRepository<CreditCenter, Long> {
    @Query("SELECT CC.id, CC.loanId, CC.clientId FROM CreditCenter CC")
    List<CreditCenter> findAllIds();
}

When I call this method from my controller, it does not throw any error, but, when I try to iterate it throws classcastexception

List<CreditCenter> objects = findAllIds();
for (CreditCenter cc : objects) { //This line throws ClassCastException
    //some logic
}
like image 866
user2023507 Avatar asked Apr 17 '14 01:04

user2023507


People also ask

What is @query annotation used for?

In order to define SQL to execute for a Spring Data repository method, we can annotate the method with the @Query annotation — its value attribute contains the JPQL or SQL to execute. The @Query annotation takes precedence over named queries, which are annotated with @NamedQuery or defined in an orm. xml file.

How does @query work in spring boot?

The @Query annotation declares finder queries directly on repository methods. While similar @NamedQuery is used on domain classes, Spring Data JPA @Query annotation is used on Repository interface. This frees the domain classes from persistence specific information, which is a good thing.

How JPQL works?

Java Persistence Query languageIt is used to create queries against entities to store in a relational database. JPQL is developed based on SQL syntax. But it won't affect the database directly. JPQL can retrieve information or data using SELECT clause, can do bulk updates using UPDATE clause and DELETE clause.

Which is JPQL aggregate function?

JPQL supports the five aggregate functions of SQL: COUNT - returns a long value representing the number of elements. SUM - returns the sum of numeric values. AVG - returns the average of numeric values as a double value.


2 Answers

Ok It seems that you are using a projection over the entity CreditCenter

@Query("SELECT CC.id, CC.loanId, CC.clientId FROM CreditCenter CC")

My first thought is : Why you dont use something like this.

 @Query("SELECT CC FROM CreditCenter CC")

that will return the list of the entities, however probably you dont want to return all the fields so my second advice is use this query.

@Query("SELECT new package.to.CreditCenter(CC.id, CC.loanId, CC.clientId) FROM CreditCenter CC")

and add a constructor in Creditcenter that support the order and type of parameters. That will work using JPQL and as jpa repos use that it should work.

public class CreditCenter {

 //Member vars
 public CreditCenter (int id, int loadid, int clientid){...}
}
like image 162
Koitoer Avatar answered Oct 21 '22 09:10

Koitoer


If you want to selectively return parts of the entity, the recommended way to do so in JPA is dedicated DTO types also known as projection classes. For this particular query you'd go ahead with something like this:

class CreditCenterExcerpt {

  private int id, loanId, clientId;

  public CreditCenterExcerpt(int id, int loadid, int clientid) { … }
}

and then use it in a way similarly to the one described by Koitoer.

interface CrediCenterRepository implements Repository<CreditCenter, Integer> {

  @Query("select new ….CreditCenterExcerpt(CC.id, CC.loanId, CC.clientId) from CreditCenter CC")
  List<CreditCenterExcerpt> yourSpecialQueryMethod();
}

The reason I wrote this up as a separate answer is that using the entity type itself has quite a few drawback (hence the recommendation of the separate type in the first place):

The instances returned from a projecting query execution are detached by definition no matter whether the EntityManager is still open or not. By using a separate type for those calls, you don't accidentally create the impression that the object returned was a fully-populated and managed entity instance.

A developer not aware of the projection might just use the instance returned, try to access properties not populated or even try to save the instance in turn and thus wipe out all the properties not loaded in the first place.

like image 37
Oliver Drotbohm Avatar answered Oct 21 '22 09:10

Oliver Drotbohm