2

我正在使用 java spring boot 的后端分页和排序pageable。在将排序字段作为usercount(这给出计数user_role_mapping)传递时,Java 触发错误列 f.usercount 不存在。实际上usercount不是一个列,它是一个别名。

如何使用usercount作为不带f 的别名名称进行排序。作为前缀?

接口网址:

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

默认的 sortBy & sortType在控制器层分别是iddesc 。

Java代码如下:

Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).descending());
if (sortType.equalsIgnoreCase("asc")) {
    pageable = PageRequest.of(pageNumber, pageSize, 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);
4

2 回答 2

2

问题是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, pageSize, 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);
}
于 2020-09-18T08:10:41.737 回答
1

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

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

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

使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:

@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 的替代品!

于 2020-09-18T07:10:18.207 回答