Spring Data Rest如何对带有下划线的字段进行排序

12
我们正在使用很简单的设置,将@RepositoryRestResource应用于连接到PostgreSQL数据库的PagingAndSortingRepository。此外,我们配置了spring.jackson.property-naming-strategy=SNAKE_CASE来返回漂亮的JSON。但当我们开始排序时就出现问题了。因为我们发现,排序需要我们提供实际的类字段名称(它们当然是驼峰式的):

get("/thing?sort=dateCreated,desc")

当我们尝试进行 JavaScript 友好的如下格式时:

get("/thing?sort=date_created,desc")

它失败了,因为 JPA 试图通过下划线拆分参数。

有没有一种简单的方法来使路径参数与我们返回的 JSON 中的格式相同呢?


你尝试过使用 __(2个下划线)吗?(参见https://dev59.com/B4rda4cB1Zd3GeqPLV18) - user180100
是的,那也不起作用。似乎 __ 只适用于自定义方法。 - Rince
尝试复现,但它运行良好 -> github上的代码。您使用的是哪些版本? - jannis
2个回答

10
这里有一个bug- DATAREST-883,已经被修复并发布。但是由于回归 (DATAREST-909),这个问题在下一个版本中被删除了。我在 Github上问过他们 ,是否计划再次添加此功能,因为这个问题以前也曾困扰我。我们将看看他们对此的看法。
目前,您可以:
  • 不管它
  • 使用驼峰式属性名称
  • 解决此问题(例如采用Alan Haye's answer)- 我认为这似乎很脆弱,但可能在短期内会起作用。
在我测试的spring-boot版本中,该功能的状态如下:
  • 1.4.0 (spring-data-rest 2.5.2):尚未实现
  • 1.4.1 (spring-data-rest 2.5.3):可用 -> 代码
  • 1.4.2 (spring-data-rest 2.5.5):删除

哇,感谢您的调查!我们会等待直到它被修复 :) - Rince
看起来在 sdr 3.4.6 版本中仍然存在这个问题... - Kevvvvyp
1
根据此问题,仍然保持开放状态。 - Arnau Aregall

4

目前尚不清楚是否可以使用Spring Data Rest特定的方式来完成此操作,但是您应该能够通过标准的Servlet过滤器处理它,示例如下:

public class SortParameterConversionFilter extends GenericFilterBean {

    // as we are extending Spring's GenericFilterBean
    // you can then *possibly* inject the RepositoryRestConfiguration
    // and use  RepositoryRestConfiguration#getSortParamName
    // to avoid hard coding
    private static final String SORT_PARAM_KEY = "sort";

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;

        if (shouldApply(request)) {
            chain.doFilter(new CollectionResourceRequestWrapper(request), res);
        } else {
            chain.doFilter(req, res);
        }
    }

    /**
     * 
     * @param request
     * @return True if this filter should be applied for this request, otherwise
     *         false.
     */
    protected boolean shouldApply(HttpServletRequest request) {
        return request.getServletPath().matches("some-pattern");
    }

    /**
     * HttpServletRequestWrapper implementation which allows us to wrap and
     * modify the incoming request.
     *
     */
    public class CollectionResourceRequestWrapper extends HttpServletRequestWrapper {

        public ResourceRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getParameter(final String name) {
            if (name.equals(SORT_PARAM_KEY)) {
                String [] parts = super.getParameter(SORT_PARAM_KEY).split(",");
                StringBuilder builder = new StringBuilder();

                int index = 0;

                for (String part : parts) {
                    // using some mechanism of you choosing
                    // convert from underscore to camelCase
                    // Using the Guava library for example
                    String convertedPart = CaseFormat.LOWER_UNDERSCORE.to(
                         CaseFormat.LOWER_CAMEL, part);
                    ++index;
                    builder.append(convertedPart).append(index < parts.length ? "," : "");
                }

                return builder.toString();
            }

            return super.getParameter(name);
        }
    }
}

在我的情况下,我需要使用 getParameterValues 而不是 getParameter - Paulo Mateus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接