Spring Data JPA - 是否可以对计算属性进行排序?

12

假设您有以下实体:

@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;
            }
        }
    }
}
如果我的`GameRepository`是一个`PagingAndSortingRepository`,我该如何获取按`status`属性排序的结果页?
当前情况:
java.lang.IllegalArgumentException: Unable to locate Attribute  with the the 
given name [status] on this ManagedType [org.test.model.Game]

我可以理解这一点,因为status确实不是JPA属性。是否有什么方法可以绕过这个问题呢?

(我正在使用Hibernate,所以任何基于Hibernate的特定方法也可以)


2
也许可以通过一个公式来替换你的getStatus方法,参见https://dev59.com/n4nda4cB1Zd3GeqPCKrA#29625652。 - user180100
2个回答

15

问题在于Spring Data的PageRequest排序是通过组成ORDER BY子句来在数据库层面执行的。

您可以创建一个@Formula列,例如:

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

那么,使用新列按排序顺序进行排序将成为可能,因为您在公式中编写的所有内容都将传递到ORDER BY子句。


我已经接受了这个答案,因为这可能是唯一的方法,但在一个HQL语句中完成所有逻辑似乎非常困难。 - Wim Deblauwe
1
你也可以创建一个包含计算列的数据库视图,并将实体映射到该视图。 - ike3

2

使用注解@Formula

示例:ticketPrice = 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;
}

要按照此列排序,必须将其作为列结果存在。
GET example-url?size=25&page=0&sort=ticketPrice,ASC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接