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

9
我们使用Spring Data在分页和可排序的表格中显示计算字段列表:
@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);

除了排序支持以外,一切都能正常工作。
要对计算字段进行排序,Spring Data(或JPA?)会自动附加以下语句:
... order by c.toAllocateAmount desc

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

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

... order by toAllocateAmount desc

问题是:是否有一种方法或变通方法,可以告诉Spring Data生成自定义的order by语句。一些映射告诉它根据所需的排序字段生成代码?
1个回答

7
简短回答:将原始分页对象中的排序字段用括号括起来进行封装,格式如下:
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)) ;
}

为了理解原因,请看一下Spring Data在使用分页请求时如何生成“order by”子句:QueryUtils.getOrderClause()。这听起来更像是一个hack而不是一个真正的解决方案,但它可以正常工作。
如果您想使用从查询结果得到的Pageable对象(Page<T>),则可能需要删除先前添加的括号。(用例:在数据表头中显示排序列)

2
对我来说,我还需要添加一个unsafe:JpaSort.unsafe(Sort.Direction.ASC,“(broadcastTitle)”); - wessel

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