我有一个我要订购的表格列 . 问题是列值包含数字和文本 . 例如,结果现在按此顺序排序 .
1. group one
10. group ten
11. group eleven
2. group two
但我希望自然地订购结果,就像这样
1. group one
2. group two
10. group ten
11. group eleven
在查看Spring配置时,我似乎无法找到允许您执行此操作的选项 . 我使用Spring Pageable类设置我的订单字段和方向,另外使用JPA规范 . 默认情况下,该方法本身返回一个包含前20个结果的Page .
我不相信Oracle支持开箱即用的自然排序,所以我有一个存储过程 . 使用此过程运行查询,我得到了所需的结果 .
select ... from group order by NATURALSORT(group.name) asc
正如您所料,我希望通过将其包装在包含文本的每个有序列周围来使用该过程 . 同时保持使用可分页/页面和规范 . 我在这方面所做的研究指出了一个可能包括的解决方案
-
创建和实现自定义规范
-
或者扩展SimpleJpaRepository以更改Sort对象的转换方式 .
但我似乎没有找到允许我使用本机SQL设置顺序的方法 . 我找到设置顺序的唯一方法是调用 orderBy
并包含一个 Order
对象 .
所以总的来说 .
-
使用Spring Data Jpa,hibernate和Oracle数据库时,有没有办法全局启用自然排序
-
如果没有,如何在仍然能够使用
Page findAll(Pageable, Specifications)
方法的同时用我的存储过程包装单个order by column
?
提前致谢 .
2 回答
我不知道有任何这样的功能 . 但是,您可以将数字存储在单独的列中,然后按该列排序,这样可以提供更好的排序性能作为额外的好处 .
在深入研究Spring JPA和Hibernate的源代码后,我设法找到了解决问题的方法 . 我很确定这不是解决问题的好方法,但它是我唯一能找到的方法 .
我最终通过扩展
SingularAttributePath
类为查询的'order by'部分实现了一个包装器 . 此类有一个render方法,用于生成插入实际查询的字符串 . 我的实现看起来像这样接下来,我扩展了SimpleJpaRepository类中的Order转换功能 . 默认情况下,这是通过调用
QueryUtils.toOrders(sort, root, builder)
来完成的 . 但由于调用它的方法无法覆盖,我最终自己调用toOrder
方法并根据自己的喜好改变结果 .这意味着通过我自定义的
SingularAttributePath
类实现替换结果中的所有订单 . 作为一个额外的我扩展了Sort
类,Pageable
类使用它来控制被包裹的内容以及在一秒内得到的内容 . 我的实现看起来很接近(一些检查被遗漏)然后通过调用
query.orderBy(resultlist)
将返回列表添加到查询中 . 那就是后端 .为了控制换行条件,我还扩展了
Pageable
使用的Sort
类(提到这几行) . 我想要添加的唯一功能是在Direction枚举中有4种类型 .ASC(默认升序)
DESC(默认降序)
NASC(正常上升)
NDESC(正常下降)
最后两个值仅用作占位符 . 它们设置了
isNatural
布尔值(扩展Order
类的变量),它在条件中使用 . 在将它们转换为查询时,它们将映射回其默认变体 .最后我更换了
PageableHandlerMethodArgumentResolver
使用的SortHandlerMethodArgumentResolver
. 这样做的唯一方法是创建我的NaturalSort
类的实例并将它们传递给Pageable对象,而不是默认的Sort
类 .最后,我能够调用相同的REST endpoints ,而结果的排序方式不同 .
我希望这个解决方案可以帮助那些在自然排序和 spring JPA方面有相同或衍生问题的人 . 如果您有任何疑问或改进,请告诉我 .