我需要能够编辑Pageable对象,更具体地说是Sorts之一。
我有一些DTO Member
,其属性为emailAddress
。客户端不知道这是由来自Account
或Invite
两个不同实体的查询收集的信息。 Member
始终具有其中之一。
这足够好,我在仓库中执行了一个标准的JPA查询,并在将其转换为DTO之前收集了所需的信息。
现在,我们要对该引用的属性进行排序。没关系。我可以创建一个查询,其中包含类似ORDER BY coalesce(i.emailAddress, a.emailAddress) ASC
这样的查询,效果很好。如果客户端未在Pageable对象中通过任何排序,则仅使用此排序,如果客户端通过了排序,那么我将调用没有此默认排序的其他版本的查询。
但是现在客户希望对该emailAddress
属性进行排序,麻烦就开始了。直接将Pageable
传递到Repository
不起作用,因为没有属性emailAddress
。所以我认为不用担心!让我们检查一下我的代码是否对该属性进行排序,并根据参数对查询进行特殊版本处理。
if (pageable.getSort().isSorted()) {
Sort.Order emailAddressOrder = pageable.getSort().getOrderFor("emailAddress");
if (emailAddressOrder != null) {
if (emailAddressOrder.getDirection() == Sort.Direction.ASC)
members = memberRepo.findInProjectDefaultSortAsc(projectId, skipFullName, fullName, pageable);
else
members = memberRepo.findInProjectDefaultSortDesc(projectId, skipFullName, fullName, pageable);
}
else
members = memberRepo.findInProject(projectId, skipFullName, fullName, pageable);
}
else
members = memberRepo.findInProjectDefaultSortAsc(projectId, skipFullName, fullName, pageable);
看起来不漂亮,但应该正常工作吗?错误的,因为Pageable
仍然包含无效的属性emailAddress
。
那么如何删除此属性?我尝试将其强制转换为PageRequest
,但即使该实现对象也是不可写的。我现在所做的是:
PageRequest newPageRequest = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize());
然后我将此新对象传递给查询。但这似乎容易出错,如果稍后将PageRequest实体扩展为具有其他属性的情况,那么我的对象仍然仅复制2个属性。这真的是我现在能做的最好的吗?
答案 0 :(得分:2)
是的,不用担心。您的方法没有错。 Pageable
/ PageRequest
是不可变的,这实际上是一个好习惯。使用不可变类时,通常的做法是创建具有(可能是)修改后属性的副本。
此外,不要担心未来。如果PageRequest
实体在将来得到扩展,Spring开发人员几乎肯定会使其保持不变。构造函数/工厂方法中将有一个新参数,这将导致编译错误。在升级库的版本时,发生这种错误是最好的。
编辑:您还有一个选择:不要将Sort
嵌入Pageable
中。将它们用作两个单独的参数。没有任何排序信息的第一个参数将是Pageable
。第二个参数可以是Spring的Sort
,但您也可以自由使用自己的数据类型,例如一些enum
。