Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data JPA - Is it possible to sort on a calculated property?

Suppose you have the following Entity:

@Entity
public class Game {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    private Calendar startTime;
    private int durationInSeconds;

    public GameStatus getStatus() {
        if( startTime.after(Calendar.getInstance()))
        {
            return GameStatus.SCHEDULED;
        } else {
            Calendar endTime = Calendar.getInstance();
            endTime.setTime(startTime.getTime());
            endTime.roll(Calendar.SECOND, durationInSeconds);

            if( endTime.after(Calendar.getInstance())) {
                return GameStatus.OPEN_FOR_PLAY;
            }
            else {
                return GameStatus.FINISHED;
            }
        }
    }
}

If my GameRepository is a PagingAndSortingRepository, how can I get a page of results, sorted by the status property?

I currently get:

java.lang.IllegalArgumentException: Unable to locate Attribute  with the the 
given name [status] on this ManagedType [org.test.model.Game]

Which I can understand since status is indeed no JPA attribute. Is there a way around this?

(I am using Hibernate underneath, so anything Hibernate specific is also ok)

like image 697
Wim Deblauwe Avatar asked May 10 '16 13:05

Wim Deblauwe


People also ask

Is Spring data JPA better than Hibernate?

Conclusion. Hibernate is a JPA provider and ORM that maps Java objects to relational database tables. Spring Data JPA is an abstraction that makes working with the JPA provider less verbose. Using Spring Data JPA you can eliminate a lot of the boilerplate code involved in managing a JPA provider like Hibernate.

What is the difference between spring JPA and Spring data JPA?

Spring Data JPA is a JPA data access abstraction. Just like JPA, Spring Data JPA cannot work without a JPA provider. Spring Data JPA offers a solution to the DDD Repository pattern or the DAO (Data Acess Object) pattern . It can also generate JPA queries on your behalf through method name conventions.

What is the advantage of Spring data JPA?

Spring Data JPA aims to significantly improve the implementation of data access layers by reducing the effort to the amount that's actually needed. As a developer you write your repository interfaces, including custom finder methods, and Spring will provide the implementation automatically.

How does findById work 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.


2 Answers

The problem is that Spring Data's PageRequest sort is done on the database layer by forming the ORDER BY clause.

You could create a @Formula column, e.g.

@Entity
public class Game {
...
     // rewrite your logic here in HQL
     @Formula("case when startTime >= endTime then 'FINISHED' ... end")
     private String status;

Then it will be possible to use the new column in sort order as everything you write in the formula will be passed to ORDER BY clause.

like image 126
ike3 Avatar answered Sep 27 '22 22:09

ike3


Use annotation @Formula

Example: tickePrice = totalAmount / admissions

@Entity
public class Event {
...
   // To avoid division by 0, and setting to 0 if admissions is 0 
   @Formula(value = "coalesce(totalAmount / NULLIF(admissions, 0), 0)")
   private Double ticketPrice;
}

To sort by this column is required to be present as a column result.

GET example-url?size=25&page=0&sort=ticketPrice,ASC
like image 32
tsunllly Avatar answered Sep 27 '22 22:09

tsunllly