英文:
Sorting expression in spring data JPA
问题
我有以下的实体类,其中 objectId 是字母数字字符串:
@Data
@Entity
@Table(name = "CASE_INFO")
public class CaseInfo {
@Id
@Column(name = "ID")
private UUID id;
@Column(name = "OBJECT_ID")
private String objectId;
}
我还有以下的仓库:
@Repository
public interface CaseInfoRepository extends JpaRepository<CaseInfo, UUID>, JpaSpecificationExecutor<CaseInfo> { }
现在,当我基于 Specification 和 Pageable 对象进行查询时,代码如下:
Specification<CaseInfo> specification = (root, query, criteriaBuilder) -> criteriaBuilder.and();
Pageable pageable = PageRequest.of(0, 25, Sort.by("objectId"));
caseInfoRepository.findAll(specification, pageable);
我想要根据 CaseInfo.objectId 的数值进行排序,这样 SQL 查询中的 order by 子句会类似于:
... order by to_number(OBJECT_ID) ...
如果我尝试像这样做:
PageRequest.of(0, 25, Sort.by("objectId"))
它会按字母顺序排序,所以 "100" 会在 "2" 前面,这对我的用例来说是错误的。
我在 https://www.baeldung.com/spring-data-jpa-query 找到了一个方法,它使用了:
JpaSort.unsafe("LENGTH(name)")
但是这似乎不起作用,因为如果我这样做:
PageRequest.of(0, 25, JpaSort.unsafe("to_number(objectId)"))
会得到错误信息 "No property to found for type CaseInfo! Did you mean 'id'?"。
有谁知道如何为 Sort 对象提供自定义表达式?
英文:
I have the following entity class where objectId is alphanumeric string
@Data
@Entity
@Table(name = "CASE_INFO")
public class CaseInfo {
@Id
@Column(name = "ID")
private UUID id;
@Column(name = "OBJECT_ID")
private String objectId;
}
I also have the following repository
@Repository
public interface CaseInfoRepository extends JpaRepository<CaseInfo, UUID>, JpaSpecificationExecutor<CaseInfo> { }
Now when I make a query based on Specification and Pageable objects like this
Specification<CaseInfo> specification = (Specification<CaseInfo>) (root, query, criteriaBuilder) -> criteriaBuilder.and();
Pageable pageable = PageRequest.of(0, 25, Sort.by("objectId"));
caseInfoRepository.findAll(specification, pageable);
I want to be able to sort result based on CaseInfo.objectId numerically so that the order by in sql query would look something like this
... order by to_number(OBJECT_ID) ...
If I do something like
PageRequest.of(0, 25, Sort.by("objectId"))
it orders alphabetically so that "100" is before "2" which is wrong for my use case.
I found https://www.baeldung.com/spring-data-jpa-query where it uses
JpaSort.unsafe("LENGTH(name)")
but this does not seem to work because if I do
PageRequest.of(0, 25, JpaSort.unsafe("to_number(objectId)"))
It gives error message "No property to found for type CaseInfo! Did you mean 'id'?"
Does anybody know a way to give custom expression to Sort object?
答案1
得分: 4
你可以添加一个公式字段,将字符串值转换为数值,并根据此字段进行排序,或者使用默认的实现findAll(Pageable pageable)
:
@Data
@Entity
@Table(name = "CASE_INFO")
public class CaseInfo {
@Id
@Column(name = "ID")
private UUID id;
@Column(name = "OBJECT_ID")
private String objectId;
@Formula(value = "CAST(OBJECT_ID AS NUMERIC(10, 0))")
private int numObjectId;
}
Repository:
@Repository
public interface CaseInfoRepository extends
JpaRepository<CaseInfo, UUID>, JpaSpecificationExecutor<CaseInfo> {
// 按公式字段排序
List<CaseInfo> findAllByOrderByNumObjectId(Pageable pageable);
}
在使用@Formula
中的CAST
函数时有一个技巧,很可能在将其转换为INT
、INTEGER
、BIGINT
时会失败,但是将其转换为NUMERIC(10, 0)
时可以正常工作。
NUMERIC
的范围应足够大,能够容纳转换后字符串中的值,否则可能会导致整数溢出。
英文:
You could add a formula field casting the string value to the numeric one and then sort by this field or use default implementation findAll(Pageable pageable)
:
@Data
@Entity
@Table(name = "CASE_INFO")
public class CaseInfo {
@Id
@Column(name = "ID")
private UUID id;
@Column(name = "OBJECT_ID")
private String objectId;
@Formula(value = "CAST(OBJECT_ID AS NUMERIC(10, 0))")
private int numObjectId;
}
Repository:
@Repository
public interface CaseInfoRepository extends
JpaRepository<CaseInfo, UUID>, JpaSpecificationExecutor<CaseInfo> {
// sort by formula field
List<CaseInfo> findAllByOrderByNumObjectId(Pageable pageable);
}
There is a trick with using CAST
function in @Formula
-- it is very likely to fail when casting to INT
, INTEGER
, BIGINT
but it works when casting to NUMERIC(10, 0)
.
Numeric
also should be large enough to contain the value within the string after cast otherwise an integer overflow may occur.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论