当前位置: 首页 > 知识库问答 >
问题:

Spring Data JPA无效的page.sort参数

濮君植
2023-03-14

在使用Spring Data JPA和Hibernate的web应用程序中,我们利用web分页功能在各种实体列表中提供分页和排序功能。

@Controller
public class MyEntityController {
   @RequestMapping(method = RequestMethod.GET)
   public ModelAndView list(Pageable pageable) { ... }
}

@Configuration
public class MyWebMvcConfig extends WebMvcConfigurationSupport {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        super.addArgumentResolvers(argumentResolvers);
        argumentResolvers.add(new PageableArgumentResolver());
    }
}

public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, String> {
    Page<MyEntity> findByPropertyX(String propertyX, Pageable pagable);
}

这允许在呈现的html中将实体属性定义为特殊的排序请求参数,其中页面。sort值实际上与要排序的实体中的属性匹配。

<table>
    <thead>
        <tr>
            <th><a href="?page.sort=propertyX&amp;page.sort.dir=asc">Property X</a></th>
            <th><a href="?page.sort=propertyY&amp;page.sort.dir=asc">Property Y</a></th>
        </tr>
    </thead>
    <tbody>...</tbody>
</table>

这将生成一个结果URL,例如:

http://host/context-root/entities/?page.sort=propertyX&page.sort.dir=asc

问题是,用户可能会修改URL以使用无效的page.sort属性,这些属性引用不存在的列/属性名称,或者更糟的是,使用无效的JPA查询字符导致无效语法。

例如,如果URL被修改为按“noSuchProperty”排序:

http://host/context-root/entities/?page.sort=noSuchProperty&page.sort.dir=asc

但此属性不存在,将引发以下异常:

java.lang.IllegalArgumentException: No property noSuchProperty found for type class com.my.company.MyEntity
    at org.springframework.data.repository.query.parser.Property.<init>(Property.java:76)
     . . .
    at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:86)
     . . .
    at $Proxy68.findByPropertyX(Unknown Source)
    at com.my.company.MyEntityRepository.findByPropertyX(MyEntityRepository.java:17

同样,如果URL被修改为无效的查询语法字符,例如“”:

http://host/context-root/entities/?page.sort=%22&page.sort.dir=asc

将发生以下错误:

java.lang.StackOverflowError
    java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
    . . .
    org.springframework.data.repository.query.parser.Property.create(Property.java:326)
    org.springframework.data.repository.query.parser.Property.create(Property.java:326)
    org.springframework.data.repository.query.parser.Property.create(Property.java:326)
    org.springframework.data.repository.query.parser.Property.create(Property.java:326)

(还有第三种类型的异常,当@Query在Repository方法上显式定义时,会导致org.hibernate.QueryExctive。)

Spring Data JPA抽象了这些参数的排序、分页和处理的细节;然而,它似乎不能很好地处理这些情况(即指定了无效的排序参数)。

我们可以添加一些额外的自定义逻辑来验证sort属性是否确实存在于实体上;然而,我想知道是否有一种更干净、更集中的方法来实现这一点,这样我们就不会失去Spring数据JPA抽象的好处和简单性。我们在整个应用程序中对许多不同的实体使用这种排序功能,因此理想情况下,我们希望更多地采用通用方法,而不必为每个请求的实体页面显式定义或检查排序属性。

具体来说,我们实际上扩展了PageableArgumentResolver来接受控制器中提供的带注释的排序缺省值(为了简单起见,代码示例中没有说明),因此我们希望回退到这个默认排序顺序,或者只是实体的默认排序顺序,而不是抛出异常。

一些想法和尝试。。我可以使用QueryCreationListener拦截查询创建并获取排序参数;然而,我实际上无法在此时修改查询。或者,我可以扩展并使用定制的PageableArgumentResolver(我们已经在这么做了)来获取排序参数;但是,我当时无法访问该实体,也无法确定该实体是否实际拥有该名称的属性。我们可以显式地声明支持的属性;然而,这又一次挫败了在不需要实体的特定或声明的知识的情况下集中和自动处理该场景的想法。

有没有其他类型的拦截器或类似的构造可以用来集中验证可分页排序参数,并在调用查询之前进行必要的修改?或者Spring是否有任何类型的配置或方式可以自动处理这种情况,从而更优雅地处理无效的排序参数?

共有2个答案

潘楚
2023-03-14

我认为改进PageableArgumentResolver来优雅地处理这些场景。它可以尝试从作为Sort提交的String创建一个属性路径实例,从而确保它是有效的实例。我有点纠结于默认情况下简单地删除无效的String是否有意义,这将返回根本没有排序的结果。这可能是最无缝的体验,但也可能导致找出结果没有排序的原因的乏味尝试。

然而,这是不可能的。如果你能在Spring Data Commons上提出一张JIRA罚单,并把这张罚单链接到这里,那就太好了。如果您已经充实了一个可行的实现,可以随意打开一个pull请求。谢谢你把这个带到桌上!

步衡
2023-03-14

我正在查看代码,我认为更多的堆栈跟踪会有所帮助。但从我看到的情况来看,如果你想重写一些Spring代码,我认为有两个地方可能需要解决。

这里有两种情况,第一种情况是传递对象/表中不存在的排序字段。你真正想要的是,这个坏参数一直被默默地忽略,而不仅仅是在传递1PageableArgumentResolver]1时。我认为,AbstractQueryCreator(因此,JpaQueryCreator)上应该有一个选项来忽略排序中的错误参数。

第二个需要解决的部分可能是PageableArgumentResolver。如果您传递空字符串或一些没有意义的东西,比如,那么它应该忽略该参数,而不是将其发送到页面请求

黑客快乐,祝你好运。阅读你的帖子让我意识到我的网站容易遇到同样的问题,我真的没有好的解决方案。

 类似资料:
  • 问题内容: 有人知道为什么chrome参数不起作用吗? 我也尝试过在切换台之前不加“-”并仅给出一个参数… Chrome启动,但没有激活的标志。 我使用最新的chromedriver。 问题答案: 我最近发现的类不与当前的硒和铬出于某种原因(如硒2.33.0,铬30和2013年7月)正常工作。 我相信,我链接的答案也是您解决问题的方法。只需使用,这些对我来说一直很好:

  • 我想让它在每天每小时的第5,15,25,35,45和55分钟运行。这似乎与这里的AWS调度事件文档一致http://docs.AWS.amazon.com/amazoncloudwatch/latest/Events/scheduledevents.html。 上面的文档允许用0到59之间的逗号分隔值表示分钟,并使用*通配符反映小时、月日(或周日)、月和年。 我尝试在Lambda控制台(创建函数并

  • 我正在上载excel工作表,并希望将其数据移动到数据库中的另一个表中。最近两天我收到了一个错误(),但是,如果我设计了一个非常简单的应用程序,它就可以正常工作。请帮帮我

  • 当我试图从我的api中点击以从keydove对用户进行身份验证时,它给了我一个错误无效参数:keydove页面上的redirect_uri。除了师父,我创造了自己的王国。KeyClope正在http上运行。请帮帮我。

  • 问题内容: 背景:我正在编写一个简单的UDP应用程序对我管理的beta服务器执行ping操作,以便告诉我它仍然可以正常运行(我无法对那些想知道的服务器启用ping操作)。我打算在手机上运行此命令,以在服务器不再响应时警告我。 我试图像这样使用看似简单的java.net.DatagramSocket: 我还要说一句,我已通过android清单启用了Internet权限,如果删除了use子句,则会出现

  • 问题内容: 我想在两个不同的程序之间发送一个打开的文件描述符。所以我用用这样做。但是我收到了ioctl的无效参数。 文件附件.h仅包含一些常见的包含文件,而没有其他内容。首先,我发送一条简单的消息,然后调用该方法,该方法首先发送2字节消息,然后必须使用ioctl发送文件描述符。但事实并非如此。 问题答案: 看来linux不支持I_SENDFD。注释表明该内容在文档中,但实际上不受支持,并会导致您遇