在使用Spring Data JPA和Hibernate的Web应用程序中,我们利用web pagination功能在各种实体列表中提供分页和排序功能.
@Controller
public class MyEntityController {
@RequestMapping(method = RequestMethod.GET)
public ModelAndView list(Pageable pageable) { ... }
}
@Configuration
public class MyWebMvcConfig extends WebMvcConfigurationSupport {
@Override
public void addArgumentResolvers(List
这允许在呈现的html中将实体属性定义为特殊排序request parameters,其中page.sort值实际匹配要排序的实体中的属性.
这会产生一个结果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.
同样,如果将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)
(当在Repository方法上显式定义@Query时,还有第三种异常会导致org.hibernate.QueryException.)
Spring Data JPA抽象出这些参数的排序,分页和处理的细节;但是,它似乎没有优雅地处理这些场景(即指定了无效的排序参数).
我们可以添加一些额外的自定义逻辑来验证实体上实际存在sort属性;但是,我想知道是否有更清晰,更集中的方法来做到这一点,这样我们就不会失去Spring Data JPA抽象的好处和简单性.我们在整个应用程序中使用这种排序功能与许多不同的实体,所以理想情况下,我们需要更多的通用方法,而不是必须明确定义或检查所请求的每个实体页面的排序属性.
具体来说,我们实际上扩展了PageableArgumentResolver以接受我们的控制器中提供的带注释的排序默认值(为简单起见,未在代码示例中说明),因此我们只想回退到此默认排序顺序,或者只是默认排序实体的订单,而不是抛出异常.
一些想法和尝试..我可以使用QueryCreationListener来拦截查询创建并获取sort参数;但是,我当时无法修改查询.或者,我可以扩展并使用自定义的PageableArgumentResolver(我们已经这样做)来获取排序参数;但是,我当时无权访问实体,也无法确定实体是否实际拥有该名称的属性.我们可以明确声明支持的属性;然而,这又失败了集中和自动处理这种情况的想法,而不需要具体或声明的实体知识.
是否有任何其他类型的拦截器或类似构造可用于集中验证可分页排序参数,并在调用查询之前根据需要进行修改?或者是否有任何类型的配置或方式,Spring可以自动处理这种情况,以便它更优雅地处理无效的排序参数?
最佳答案
我正在看一下代码,我认为更多的堆栈跟踪会有所帮助.但是从我所看到的情况来看,如果您想重写一些Spring代码,我认为有两个地方可能需要解决.
这里有两种情况,在第一种情况下,您传递的是对象/表中不存在的排序字段.你真正想要的是这个坏参数一直被忽略,而不仅仅是在传入1PageableArgumentResolver] 1时.我认为它应该是AbstractQueryCreator
(因此,JpaQueryCreator
)的选项,以忽略排序中的错误参数.
应该解决的第二部分可能是PageableArgumentResolver
.如果你传递空字符串或者那些没有意义的东西,那么它应该忽略该参数而不是将它发送到PageRequest.
快乐的黑客和好运.阅读你的帖子让我意识到我的网站容易受到同样的问题,我真的没有好的解决方案.