使用下划线的Spring数据rest排序字段

时间:2022-09-11 16:48:44

We are using a very simple setup of @RepositoryRestResource on top of a PagingAndSortingRepository connected to a postgres database. Also we have configured spring.jackson.property-naming-strategy=SNAKE_CASE to return pretty json. It was all fine and dandy until we started sorting. As we have discovered - sorting requires us to provide the actual class field names (which we of course have in camel case):

我们使用的是一个非常简单的@RepositoryRestResource的设置,它位于一个连接到postgres数据库的PagingAndSortingRepository之上。我们还配置了spring.jackson。属性命名策略=SNAKE_CASE返回漂亮的json。在我们开始分类之前,一切都很好。正如我们所发现的那样——排序要求我们提供实际的类字段名(在camel案例中当然有):

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

get(" /事? = dateCreated,desc”)

And when we try to do javascript friendly

当我们尝试做javascript友好的时候

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

get(" /事? = date_created,desc”)

it fails miserably because jpa tries to split the parameter by the underscore.

它失败得很惨,因为jpa试图通过下划线分割参数。

Is there a simple way to have the path params the same format as we have them in the json that we are returning?

是否有一种简单的方法来让路径与我们返回的json中具有相同的格式?

2 个解决方案

#1


5  

There is a bug for this - DATAREST-883. It was fixed and released. But then, due to regressions (DATAREST-909) this has been dropped in the very next release. I asked them on Github if they plan to have this again as this has bitten me in the past as well. We'll see what they have to say about this.

这个- DATAREST-883有一个错误。它被修复并释放。但是,由于回归(datarres -909),这在下一个版本中被删除了。我在Github上问他们是否还打算再来一次,因为我也曾被它咬过。我们看看他们对此有什么看法。

For now you can:

现在您可以:

  • leave it be
  • 随它去吧
  • go with the camel case property names
  • 使用骆驼箱属性名
  • work around this (e.g. go with Alan Haye's answer) - this seems fragile IMHO, but probably will do in a short term.
  • 解决这个问题(例如,按照艾伦·海伊的回答去做)——这看起来很脆弱,但可能在短期内就能做到。

The status of the feature in the recent spring-boot versions I've tested with:

在我最近测试的spring-boot版本中,这个特性的状态是:

  • 1.4.0 (spring-data-rest 2.5.2): not yet implemented -> code
  • 1.4.0 (spring-data-rest 2.5.2):尚未实现——>代码
  • 1.4.1 (spring-data-rest 2.5.3): works
  • 1.4.1(spring-data-rest 2.5.3):工作
  • 1.4.2 (spring-data-rest 2.5.5): dropped
  • 1.4.2(spring-data-rest 2.5.5):下降

#2


2  

It is unclear whether you can do this in some Spring Data Rest specific way however you should be able to handle it by means of a standard Servlet filter which would look something like the below:

目前还不清楚是否可以用Spring的数据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);
        }
    }
}

#1


5  

There is a bug for this - DATAREST-883. It was fixed and released. But then, due to regressions (DATAREST-909) this has been dropped in the very next release. I asked them on Github if they plan to have this again as this has bitten me in the past as well. We'll see what they have to say about this.

这个- DATAREST-883有一个错误。它被修复并释放。但是,由于回归(datarres -909),这在下一个版本中被删除了。我在Github上问他们是否还打算再来一次,因为我也曾被它咬过。我们看看他们对此有什么看法。

For now you can:

现在您可以:

  • leave it be
  • 随它去吧
  • go with the camel case property names
  • 使用骆驼箱属性名
  • work around this (e.g. go with Alan Haye's answer) - this seems fragile IMHO, but probably will do in a short term.
  • 解决这个问题(例如,按照艾伦·海伊的回答去做)——这看起来很脆弱,但可能在短期内就能做到。

The status of the feature in the recent spring-boot versions I've tested with:

在我最近测试的spring-boot版本中,这个特性的状态是:

  • 1.4.0 (spring-data-rest 2.5.2): not yet implemented -> code
  • 1.4.0 (spring-data-rest 2.5.2):尚未实现——>代码
  • 1.4.1 (spring-data-rest 2.5.3): works
  • 1.4.1(spring-data-rest 2.5.3):工作
  • 1.4.2 (spring-data-rest 2.5.5): dropped
  • 1.4.2(spring-data-rest 2.5.5):下降

#2


2  

It is unclear whether you can do this in some Spring Data Rest specific way however you should be able to handle it by means of a standard Servlet filter which would look something like the below:

目前还不清楚是否可以用Spring的数据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);
        }
    }
}