问题描述
我正在使用后端分页和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的替代品!