如何接受 JPA 排序值的 @OrderBy 作为动态参数?
How to accept @OrderBy of JPA sort value as a dynamic parameter?
我想根据查询参数 sort 对嵌套集合 属性 进行动态排序。
假设我有一个实体 A
class A{
@OneToMany(mappedBy="a")
private Set<B> bset;
}
class B{
private LocalDate datefield;
@ManyToOne
private C c;
}
class C
{
private Double quantity;
}
我正在使用 findAll(Specification specification,Pageable page)
调用 A 的存储库
从 UI 开始,使用排序参数调用 rest 控制器,如下模式
url?page=0&size=10&sort=bset_datefield
由于是嵌套集合,上述排序无效。
可排序字段为日期字段、数量。
我知道 @OrderBy("bset.datefield") 会起作用,但参数应该是动态的。
调用存储库上的全部查找时如何实现此目的?
无法完成,因为初始化 entityManager 时会评估注释。
最好的选择是,创建一个有序的查询,或者一旦获得列表,如果你使用 Java 8 从现在开始,使用流的排序方法排序。
你不能这样做,仅使用 Spring 数据是不可能的。
从概念上讲,您正在使用 JpaSpecificationExecutor
和 Specification
s 参数化 class A.
在指定的 findAll
方法中,您可以按任何 属性 对 A
进行排序,甚至可以按嵌套排序 A
。
您可以指示 JPA 提供程序 fetch
一个集合,按集合字段排序,但您不能对集合本身进行排序。
即使在 A
的 Specification
正文中,您使用某种涉及必须排序的集合的子查询,并且您按集合的字段建立排序在这个子查询中,我认为 - 也许应该测试 - JPA 提供者将 return class A
的实例,然后根据提供的 @OrderBy
初始化集合标准。
顺便说一下,在语义上,使用 @OrderBy
时使用 List
而不是 Set
始终是一个好习惯。
因此,如果您想对集合进行排序,我认为您唯一的选择是处理查询字符串中收到的排序条件,并在 return 将数据发送到之前通过对象比较对内存中的集合进行排序客户。
学习本教程:REST Query Language with Spring Data JPA and Querydsl
当你使用
MyUserPredicatesBuilder
它会变魔术。
@Controller
public class UserController {
@Autowired
private MyUserRepository myUserRepository;
@RequestMapping(method = RequestMethod.GET, value = "/myusers")
@ResponseBody
public Iterable<MyUser> search(@RequestParam(value = "search") String search) {
MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder();
if (search != null) {
Pattern pattern = Pattern.compile("(\w+?)(:|<|>)(\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
}
}
BooleanExpression exp = builder.build();
return myUserRepository.findAll(exp);
}
}
我想根据查询参数 sort 对嵌套集合 属性 进行动态排序。
假设我有一个实体 A
class A{
@OneToMany(mappedBy="a")
private Set<B> bset;
}
class B{
private LocalDate datefield;
@ManyToOne
private C c;
}
class C
{
private Double quantity;
}
我正在使用 findAll(Specification specification,Pageable page)
调用 A 的存储库从 UI 开始,使用排序参数调用 rest 控制器,如下模式
url?page=0&size=10&sort=bset_datefield
由于是嵌套集合,上述排序无效。 可排序字段为日期字段、数量。
我知道 @OrderBy("bset.datefield") 会起作用,但参数应该是动态的。
调用存储库上的全部查找时如何实现此目的?
无法完成,因为初始化 entityManager 时会评估注释。
最好的选择是,创建一个有序的查询,或者一旦获得列表,如果你使用 Java 8 从现在开始,使用流的排序方法排序。
你不能这样做,仅使用 Spring 数据是不可能的。
从概念上讲,您正在使用 JpaSpecificationExecutor
和 Specification
s 参数化 class A.
在指定的 findAll
方法中,您可以按任何 属性 对 A
进行排序,甚至可以按嵌套排序 A
。
您可以指示 JPA 提供程序 fetch
一个集合,按集合字段排序,但您不能对集合本身进行排序。
即使在 A
的 Specification
正文中,您使用某种涉及必须排序的集合的子查询,并且您按集合的字段建立排序在这个子查询中,我认为 - 也许应该测试 - JPA 提供者将 return class A
的实例,然后根据提供的 @OrderBy
初始化集合标准。
顺便说一下,在语义上,使用 @OrderBy
时使用 List
而不是 Set
始终是一个好习惯。
因此,如果您想对集合进行排序,我认为您唯一的选择是处理查询字符串中收到的排序条件,并在 return 将数据发送到之前通过对象比较对内存中的集合进行排序客户。
学习本教程:REST Query Language with Spring Data JPA and Querydsl
当你使用
MyUserPredicatesBuilder
它会变魔术。
@Controller
public class UserController {
@Autowired
private MyUserRepository myUserRepository;
@RequestMapping(method = RequestMethod.GET, value = "/myusers")
@ResponseBody
public Iterable<MyUser> search(@RequestParam(value = "search") String search) {
MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder();
if (search != null) {
Pattern pattern = Pattern.compile("(\w+?)(:|<|>)(\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
}
}
BooleanExpression exp = builder.build();
return myUserRepository.findAll(exp);
}
}