Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use projection interfaces with pagination in Spring Data JPA?

I'm trying to get a page of a partial entity (NetworkSimple) using the new feature of spring data, projections

I've checked the documentation and if I request only:

Collection<NetworkSimple> findAllProjectedBy();

It works, but if I'm using pageable:

Page<NetworkSimple> findAllProjectedBy(Pageable pageable);

It throws an error:

org.hibernate.jpa.criteria.expression.function.AggregationFunction$COUNT cannot be cast to org.hibernate.jpa.criteria.expression.CompoundSelectionImpl

Any one has already work with this ?

My NetworkSimple class is the following:

public interface NetworkSimple {
    Long getId();

    String getNetworkName();

    Boolean getIsActive();
}
like image 463
David Magalhães Avatar asked Apr 18 '16 18:04

David Magalhães


People also ask

How do you fetch a one to many DTO projection with JPA and Hibernate?

Fetching a one-to-many DTO projection with JPA and Hibernate. The postDTOMap is where we are going to store all PostDTO entities that, in the end, will be returned by the query execution. The reason we are using the postDTOMap is that the parent rows are duplicated in the SQL query result set for each child record.

What are projections in Spring Data JPA?

4. Class-Based Projections. Instead of using proxies Spring Data creates from projection interfaces, we can define our own projection classes. For a projection class to work in tandem with a repository interface, the parameter names of its constructor must match the properties of the root entity class.

What is DTO projection?

You define a DTO projection in a CriteriaQuery in a pretty similar way as you do in JPQL. But instead of using the new keyword to specify the constructor call in a query String, you call the construct method on the CriteriaBuilder with a reference to the DTO class and a List of constructor parameters.

How do you return Dtos from native queries with Spring Data JPA?

Interface-based DTO projections You first need to define an interface that defines a getter method for each attribute your projection shall contain. At runtime, Spring Data JPA then generates a class that implements that interface. you can then use that interface as the return type of a repository method.


2 Answers

Note: This feature should work in the way described by the original poster but due to this bug it didn't. The bug has been fixed for the Hopper SR2 release, if you're stuck on an earlier version then the workaround below will work.

It is possible to use Pageable with the new query projection features introduced in Spring Data JPA 1.10 (Hopper). You will need to use the @Query annotation and manually write a query for the fields you require, they must also be aliased using AS to allow Spring Data to figure out how to project the results. There is a good example in spring-boot-samples part of the spring boot repository.

In your example it would be quite simple:

@Query("SELECT n.id AS id, n.name AS networkName, n.active AS isActive FROM Network n")
Page<NetworkSimple> findAllProjectedBy(Pageable pageable);

I have made the assumption that your entity looks something like this:

@Entity
public class Network
{
    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String name;

    @Column
    private boolean active;

    ...
}

Spring Data will derive a count query automatically for the paging information. It is also possible to make use of joins in the query to fetch associations and then summarise them in the projection.

like image 144
Robert Hunt Avatar answered Oct 17 '22 10:10

Robert Hunt


I think you need create findAllProjectedBy() as specification.Then you can use findAll() method like this.

example :findAll(findAllProjectedBy(),pageable)

Following link may be help to find how to create specification in spring.

https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

like image 1
Hasitha Diluka Avatar answered Oct 17 '22 12:10

Hasitha Diluka