在后端java春季启动排序中,如何使用pageable对别名进行排序?没有父表作为前缀

问题描述

我正在使用后端分页和Java Spring Boot pageable进行排序。在将排序字段传递为usercount时(此计数为user_role_mapping),Java触发了错误 f.usercount列不存在。 实际上,usercount不是列,而是别名。

如何使用用户作为Alies名称而不以 f。作为前缀进行排序?

API URL:

http://localhost:8080/facility/list?pageNumber=0&pageSize=10&sortBy=usercount&sortType=asc

在控制器层中,认sortBy和sortType分别为 id desc

Java代码如下:

Pageable pageable = PageRequest.of(pageNumber,pageSize,Sort.by(sortBy).descending());
if (sortType.equalsIgnoreCase("asc")) {
    pageable = PageRequest.of(pageNumber,Sort.by(sortBy).ascending());
}
Page<FacilityProjection> facilityList = facilityRepository.facilityListing(12,pageable);

Postgres sql Hibernate查询,用于根据功能ID列出设施详细信息以及用户数,如下所示:

@Query(nativeQuery = true,value = " Select f.name as facilityname,f.id as facilityid,count(urm.id) as usercount 
 from facility f
 join user u on f.user_id=u.id 
 join user_role_mapping urm on u.id = urm.user_id 
 where urm.role_id=:roleId ")
Page<FacilityProjection> facilityListing(@Param("roleId") Long roleId,Pageable pageable);

解决方法

问题在于usercount是聚合函数的结果。要通过此字段进行查询,查询必须包含order by count(urm.id)而不是order by usercount

在这种情况下,建议您使用Collections::sort

boolean sortByUserCount = sortBy.equalsIgnoreCase("usercount");
boolean desc = sortType.equalsIgnoreCase("desc");

final Pageable pageable;

if (sortByUserCount) {
    pageable = PageRequest.of(pageNumber,pageSize);
} else {
    if (desc) {
        pageable = PageRequest.of(pageNumber,pageSize,Sort.by(sortBy).descending());
    } else {
        pageable = PageRequest.of(pageNumber,Sort.by(sortBy).ascending());
    }
}

Page<FacilityProjection> facilityList = facilityRepository.facilityListing(12,pageable);

if (sortByUserCount) {
    Comparator<FacilityProjection> comparator = Comparator.comparing(FacilityProjection::getUserCount);

    if(desc) {
        comparator = comparator.reversed(); 
    }
    Collections.sort(facilityList.getContent(),comparator);
}
,

据我所知,这是不可能的。

话虽如此,我认为这是Blaze-Persistence Entity Views的完美用例。

我创建了该库,以允许在JPA模型与自定义接口或抽象类定义的模型之间轻松进行映射,例如类固醇上的Spring Data Projections。这个想法是,您可以按自己喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(获取器)映射到实体模型。

针对您的用例的DTO模型可能与Blaze-Persistence Entity-Views相似,如下所示:

@EntityView(Facility.class)
public interface FacilityProjection {
    @IdMapping
    Long getId();
    String getName();
    @Mapping("SIZE(users)")
    Long getUsercount();
}

查询是将实体视图应用于查询的问题,最简单的方法就是按ID查询。

FacilityProjection a = entityViewManager.find(entityManager,FacilityProjection.class,id);

Spring Data集成使您可以像使用Spring Data Projections:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features一样使用它,因此您可以将其视为支持更多用例的Spring Data Projections的替代品!