英文:
In back end (java spring boot) sorting, how to sort with Alias name using pageable? Without parent table as prefix
问题
我正在使用Java Spring Boot的pageable
进行后端分页和排序。在将排序字段设为usercount
(这会给出user_role_mapping
的计数)时,Java会触发错误column f.usercount不存在。
实际上,usercount
不是一个列名,而是一个别名。
如何在排序时使用usercount作为别名,而不带上**f.**作为前缀?
API网址:
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, pageSize, Sort.by(sortBy).ascending());
}
Page<FacilityProjection> facilityList = facilityRepository.facilityListing(12,pageable);
用于列出设施详细信息以及基于角色ID的用户计数的Postgres SQL Hibernate查询如下:
@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);
英文:
I am using backend pagination and sorting with java spring boot pageable
. While passing sort field as usercount
(This gives count of user_role_mapping
), Java triggering an error column f.usercount does not exist .
Actually usercount
not a column it's an Alias name.
How to sort using usercount as Alies name without f. as prefix?
API URL:
http://localhost:8080/facility/list?pageNumber=0&pageSize=10&sortBy=usercount&sortType=asc
Default sortBy & sortType are id and desc respectively in controller layer.
Java Code give below:
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 query for listing facility details along with user count based on role id, given below:
@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);
答案1
得分: 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);
}
英文:
The problem is that usercount
is aggregation function result. To order by this field query have to contain order by count(urm.id)
instead of order by usercount
.
In this case I'd suggest you to resort page content using 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);
}
答案2
得分: 1
据我所知,这是不可能的。
话虽如此,我认为这是Blaze-Persistence Entity Views的一个完美用例。
我创建了这个库,以便实现JPA模型与自定义接口或抽象类定义的模型之间的轻松映射,有点类似于功能强大的Spring Data Projections。这个想法是,你可以根据自己的喜好定义目标结构(领域模型),并通过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的替代品!
英文:
As far as I know, this is not possible.
Having said that, I think this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
@EntityView(Facility.class)
public interface FacilityProjection {
@IdMapping
Long getId();
String getName();
@Mapping("SIZE(users)")
Long getUsercount();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
FacilityProjection a = entityViewManager.find(entityManager, FacilityProjection.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features so you can see this as a replacement for Spring Data Projections that supports more use cases!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论