Spring Data JPA无效的page.sort参数

she*_*ley 6 java spring spring-data spring-data-jpa

在使用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);
}
Run Code Online (Sandbox Code Playgroud)

这允许在呈现的html中将实体属性定义为特殊的排序请求参数,其中该page.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>
Run Code Online (Sandbox Code Playgroud)

这会产生一个结果URL,例如:

http://host/context-root/entities/?page.sort=propertyX&page.sort.dir=asc
Run Code Online (Sandbox Code Playgroud)

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

例如,如果修改URL以对"noSuchProperty"进行排序:

http://host/context-root/entities/?page.sort=noSuchProperty&page.sort.dir=asc
Run Code Online (Sandbox Code Playgroud)

但是此属性不存在,将抛出以下异常:

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
Run Code Online (Sandbox Code Playgroud)

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

http://host/context-root/entities/?page.sort=%22&page.sort.dir=asc
Run Code Online (Sandbox Code Playgroud)

将发生以下错误:

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)
Run Code Online (Sandbox Code Playgroud)

(还有例外这导致的第三香味org.hibernate.QueryException@Query明确地对存储库的方法限定.)

Spring Data JPA抽象出这些参数的排序,分页和处理的细节; 但是,它似乎没有优雅地处理这些场景(即指定了无效的排序参数).

我们可以添加一些额外的自定义逻辑来验证实体上实际存在sort属性; 但是,我想知道是否有更清晰,更集中的方法来做到这一点,这样我们就不会失去Spring Data JPA抽象的好处和简单性.我们在整个应用程序中使用这种排序功能与许多不同的实体,所以理想情况下,我们需要更多的通用方法,而不是必须明确定义或检查所请求的每个实体页面的排序属性.

具体来说,我们实际上扩展了PageableArgumentResolver接受在我们的控制器中提供的带注释的排序默认值(为简单起见未在代码示例中说明),因此我们只想回退到此默认排序顺序,或者只是默认排序顺序对于实体,而不是抛出异常.

一些想法和尝试..我可以用a QueryCreationListener来拦截查询创建并获取sort参数; 但是,我当时无法修改查询.或者,我可以扩展并使用自定义PageableArgumentResolver(我们已经这样做)来获取排序参数; 但是,我当时无权访问实体,也无法确定实体是否实际拥有该名称的属性.我们可以明确声明支持的属性; 然而,这又失败了集中和自动处理这种情况的想法,而不需要具体或声明的实体知识.

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

sbz*_*oom 3

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

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

应该解决的第二部分可能是PageableArgumentResolver. 如果您传递空字符串或一些没有意义的东西%20,那么它应该忽略该参数并且不将其发送到PageRequest.

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