Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data returning List<Object[]>

I have this repository:

@Repository
public interface ProductRepository extends JpaRepository<Product, Long>{

@Query("SELECT p.textToSearch as text, count(*) as counter FROM Product p GROUP BY text_to_search ORDER BY counter DESC")
List<TopProductDTO> findTopProducts();
}

where the TopProductDTO class is:

public class TopProductDTO {

public TopProductDTO() {}

private String text;
private Integer counter;

// Getters and Setters are omited
}

But when I execute the code

List<TopProductDTO> topProducts = productRepository.findTopProducts();

It returns a

List<Object[]> insted a List<TopProductDTO>

As like each column is a index of the Object Array in the list... Wasn't it supposed to Spring Data binds the 'text' and 'counter' columns from query with the fields in TopProductDTO?

As result I got a this error in my Thymeleaf Template:

00:37:22.659 [http-nio-8080-exec-5] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "topProductDTO.text" (products/top:46)] with root cause
org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 14): Property or field 'text' cannot be found on object of type 'java.lang.Object[]' - maybe not public?

I'm using Spring Boot 1.3.3 and Postgres 9.2

like image 656
Vitor Vezani Avatar asked Mar 01 '16 03:03

Vitor Vezani


People also ask

What is difference between JpaRepository and CrudRepository?

CrudRepository provides CRUD functions. PagingAndSortingRepository provides methods to do pagination and sort records. JpaRepository provides JPA related methods such as flushing the persistence context and delete records in a batch.

What does findById return in JPA?

Its findById method retrieves an entity by its id. The return value is Optional<T> . Optional<T> is a container object which may or may not contain a non-null value. If a value is present, isPresent returns true and get returns the value.

What is @query annotation in spring boot?

The @Query annotation takes precedence over named queries, which are annotated with @NamedQuery or defined in an orm. xml file. It's a good approach to place a query definition just above the method inside the repository rather than inside our domain model as named queries.

How do you return a map result from a JPA or Hibernate query?

If a given JPA GROUP BY query returns only two columns where one is unique, it's very suitable to return the result as a Java Map. For this, you can use either the Java Stream functionality or the Hibernate-specific ResultTransformer .


1 Answers

Try to use the constructor of your DTO.

Declare a new constructor

public TopProductDTO(String text, Integer count) {
    this.text = text;
    this.count = count;
}

In your query use the new Constructor

@Query("SELECT new TopProductDTO(p.textToSearch, count(id))FROM Product p GROUP BY text_to_search ORDER BY counter DESC")
List<TopProductDTO> findTopProducts();
}

Use the fully qualified name of your class.

like image 83
josivan Avatar answered Oct 10 '22 10:10

josivan