Spring Data JPA 按属性排序,无需硬编码

Posted

技术标签:

【中文标题】Spring Data JPA 按属性排序,无需硬编码【英文标题】:Spring Data JPA sorting by property without hardcoding 【发布时间】:2021-11-13 23:44:18 【问题描述】:

我的实体有几个字段:

public class Some 
 private Foo foo;
 private Bar bar;

我希望有能够根据请求按 foo 排序和按 bar 排序的代码。我知道有这样的工具可以使用:

Sort sort = Sort.by(Sort.Direction.DESC, "foo");
Pageable pageable = PageRequest.of(page, limit, sort);

但似乎这种方法并不完美,因为字段名称是硬编码的,并且在某些字段名称被更改并且开发人员忘记更新此排序代码的情况下,在编译/启动阶段一切看起来都很好,但在运行时会失败.

是否有可能有替代解决方案而无需硬编码和多次复制相同的方法来更改 jpql 查询?

【问题讨论】:

没有。您可以使用 JPA 元数据(如果已生成)来获取名称(这将导致编译器错误)或编写更广泛的测试。但是排序也可以在您的控制器中从请求中构造(因此用户自己选择它们)。 旁注:不是硬编码字段名称,通常意味着让它们由调用者传递并发送到数据存储区。这通常是一场安全噩梦(SQL 注入,...)。恕我直言,硬编码字段名称“是一项功能,而不是错误”。至少,您应该考虑不“以某种方式”对它们进行硬编码的安全隐患。 (是的,JPA 有帮助,因为与原生 / JPQL 相比,使用 Criteria API 进行 SQL 注入通常是不可能的,但您始终必须至少考虑安全性)。 @M.Deinum 从控制器传递参数对我认为的代码支持/更改没有帮助。 @GPI 我并不是要将此参数从某处传递给 DS。我想也许有一些基于反射/注释的功能,这个功能将验证字段名称的更改。 正如我所提到的,您可以为此使用 JPA 元数据。您需要修改您的构建以生成它并使用它而不是字符串作为名称。这样,如果您删除或重命名字段编译将失败。 (直到您再次从 ui 中开始使用具有字符串类型的字段)。 【参考方案1】:

如果您不想使用 String 作为名称,您可以使用 JPA 元模型。此元模型您还可以使用带有条件 API 的创建查询。

Here 是一篇很好的博客文章,它解释了如何生成和使用 JPA 标准元模型。但简而言之,它归结为在你的编译器中添加一个 Maven 插件(或 Gradle,如果你使用它)。在编译期间,它现在将生成元模型。

使用您的示例类

public class Some 
 private Foo foo;
 private Bar bar;

它将生成一个Some_ 类,然后您可以使用它来获取属性的名称。 Some_.FOO 将链接到 foo 属性。现在,如果您将 foo 重命名为 bar,编译将失败,因为 Some_FOO 不再可用。

【讨论】:

这就是我想要的。谢谢!

以上是关于Spring Data JPA 按属性排序,无需硬编码的主要内容,如果未能解决你的问题,请参考以下文章

基于可编辑位置属性的 Spring Data JPA 自动排序行

如何在 Spring Data JPA 排序中定义空处理?

如何通过分页在 Spring Data JPA 中的 SELECT 子句中按别名对投影进行排序?

spring data JPA 中的多属性排序---养老院管理系统涉及技术整理

使用 Spring Data 按日期排序 ASC

Spring Data JPA:使用连接表进行排序和分页