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
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.
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.
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.
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 .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With