Spring数据对计算字段进行分页和排序

Gui*_*lle 6 sorting pagination jpa spring-data

我们使用spring数据在分页和可排序的表中显示已计算字段的列表:

@Query(value = 
    "select new com.mycompany.SomeDTO( " +
    "    c.id as creditAdviceId, " +
    "    case when c.associationAmount.assignedAmountNet = 0 "+
    "        then c.netReceivedAmount  "+
    "        else 0 "+
    "        end "+
    "        as toAllocateAmount, " +
    "    c.netReceivedAmount - c.associationAmount.assignedAmountNet "+
    "        as notAllocatedAmount",
    ") " +
    "from CreditAdvice c where c.debtorCompany.id = :companyId",

    countQuery = "select count(c.id) from CreditAdvice c where c.debtorCompany.id = :companyId")

Page<SomeDTO> creditAdviceMonitoring(@Param("companyId") long companyId, Pageable pageable);
Run Code Online (Sandbox Code Playgroud)

除排序支持外,其他一切工作都很好。

为了对计算所得的字段进行排序,Spring Data(或JPA吗?)会自动附加以下语句:

... order by c.toAllocateAmount desc
Run Code Online (Sandbox Code Playgroud)

这是无效的,因为在CreditAdvice实体上不存在c.toAllocateAmount。

但是在JPA控制台中测试的相同请求可以正常工作(由于select语句中的别名):

... order by toAllocateAmount desc
Run Code Online (Sandbox Code Playgroud)

问题是:有没有办法或一种解决方法来告诉Spring数据生成自定义order by子句。一些映射之王告诉他根据所需的排序字段生成的代码

Gui*_*lle 5

简短答案:用括号封装原始可分页对象的排序字段,如下所示:

public static Pageable parenthesisEncapsulation(Pageable pageable) {

    List<Sort.Order> orders = new ArrayList<>() ;
    for (Sort.Order order : pageable.getSort()) {
        String encapsulatedProperty = "("+order.getProperty()+")" ;
        orders.add( new Sort.Order(order.getDirection(), encapsulatedProperty));
    }

    return new PageRequest(pageable.getPageNumber(), pageable.getPageSize(), new Sort(orders)) ;
}
Run Code Online (Sandbox Code Playgroud)

要了解原因,请看一下使用分页请求时Spring Data如何生成“ order by”子句:QueryUtils.getOrderClause()

这听起来更像是骇客,而不是真正的解决方案...但是效果很好。

可选地,如果要使用结果查询(Page <T>)中的结果Pageable对象,则可能必须删除以前添加的括号。(用例:在数据表标题中显示排序的列)

  • 对我来说,我还需要添加一个不安全的: JpaSort.unsafe(Sort.Direction.ASC, "(broadcastTitle)"); (2认同)