jjzjj

java - Spring Data JPA 无效的 page.sort 参数

coder 2024-04-01 原文

在将 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<HandlerMethodArgumentResolver> argumentResolvers) {
        super.addArgumentResolvers(argumentResolvers);
        argumentResolvers.add(new PageableArgumentResolver());
    }
}

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

这允许在呈现的 html 中将实体属性定义为特殊类型 request parameters ,其中 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>

这会生成一个结果 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)

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

Spring Data JPA 抽象出排序、分页和处理这些参数的细节;但是,它似乎无法妥善处理这些情况(即指定了无效的排序参数)。

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

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

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

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

最佳答案

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

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

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

祝你黑客愉快,祝你好运。阅读您的帖子让我意识到我的网站也存在同样的问题,我真的没有好的解决方案。

关于java - Spring Data JPA 无效的 page.sort 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11232056/

有关java - Spring Data JPA 无效的 page.sort 参数的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  4. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  7. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  8. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  9. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  10. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

随机推荐