2012-06-27 21 views
6

Spring Data JPAとHibernateを使用するWebアプリケーションでは、web pagination機能を使用して、エンティティのさまざまなリストでページングとソート機能を提供しています。Spring Data JPA無効なpage.sortパラメータ

@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); 
} 

これはpage.sort値が実際にソートする際のエンティティ内のプロパティと一致してレンダリングされたHTMLのような特殊なソートrequest parametersで定義されるエンティティのプロパティを可能にします。

<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 

ユーザーが無効page.sortプロパティを使用するURLを変更してもよいということである問題その基準のいずれかが存在しないカラム/プロパティ名、または悪化、無効な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が明示的にリポジトリ方法で定義されている場合org.hibernate.QueryExceptionもたらす例外の第三の風味もある)

スプリングデータJPA抄録離れての詳細をソート、ページング、およびこれらのパラメータの処理。ただし、これらのシナリオ(つまり、無効なソートパラメータが指定されている場合)を適切に処理するようには見えません。

ソートプロパティが実際にエンティティに存在することを検証するカスタムロジックを追加できます。しかし、Spring Data JPAの抽象化のメリットとシンプルさを失わないように、これを行うためのよりクリーンで集中化されたアプローチがあるのだろうかと思います。私たちはこのソート機能を多くの異なるエンティティでアプリ全体に使用しています。理想的には、リクエストされたすべてのエンティティページのソートプロパティを明示的に定義したりチェックしたりする必要はありません。

具体的には、コントローラで提供されるアノテーション付きの並べ替えのデフォルト値を受け入れるように実際に拡張しています(簡単にするためにコード例には示していません)。このデフォルトの並べ替え順に戻すだけです。例外をスローするのではなく、エンティティのデフォルトのソート順です。

私はQueryCreationListenerを使用してクエリの作成をインターセプトし、並べ替えパラメータを取得できます。しかし、私は実際にその時点でクエリを変更することはできません。あるいは、私はソートパラメータを取得するためにカスタムを拡張して使用することができます(これを既に行っています)。PageableArgumentResolverしかし、私はその時点でエンティティにアクセスすることはできませんし、実体がその名前でプロパティを実際に持っているかどうかを判断する能力もありません。サポートされているプロパティを明示的に宣言できます。しかし、このことは、エンティティの特定のまたは宣言された知識を必要とせずに、このシナリオを集中的かつ自動的に処理するという考え方を打ち消してしまう。

ページング可能なソートパラメータを一元的に検証し、クエリを呼び出す前に必要に応じて変更するために使用できる、他のタイプのインターセプタまたは類似の構造体がありますか?あるいは、Springがこのシナリオを自動的に処理して、無効なソートパラメータをより適切に処理するような設定や方法がありますか?

答えて

3

私はコードを見ていましたが、スタックトレースのいくつかが役立つと思います。しかし、私が見ることのできるところでは、Springコードを書き直す気分になれば、2つの場所で取り組むことができます。

ここには2つのシナリオがありますが、最初はオブジェクト/テーブルに存在しないソートフィールドを渡しています。あなたが本当に望むのは、その悪いパラメータが、1 PageableArgumentResolver] 1を渡すときだけでなく、常に黙って無視されることです。私は、それがAbstractQueryCreator(したがって、JpaQueryCreator)のオプションで、ソートの悪いパラメータを無視するべきだと思っています。

2番目の部分はおそらくPageableArgumentResolverです。空の文字列や%20のような意味を持たないものを渡す場合は、そのパラメータを無視してPageRequestに送信しないでください。

ハッピーハッキングと幸運。あなたの記事を読んで私のサイトは同じ問題に脆弱であることに気がつきました。本当に良い解決策はありません。

1

PageableArgumentResolverを改善して、これらのシナリオを適切に処理すると思います。 StringからPropertyPathインスタンスを作成して、Sortとして渡して、それが有効であることを確認することができます。私はちょうどそれが全くソートされていない結果を返す、デフォルトで無効なStringを落とすことが理にかなっているかどうか、ちょっと解りました。これはおそらく最もシームレスな体験ですが、結果がソートされなかった理由を知るための面倒な試みにつながる可能性があります。

ただし、それです。 Spring Data CommonsとのJIRAチケットを発行して、このチケットをここにリンクさせることができれば涼しいでしょう。実行可能な実装を完成させた場合は、プルリクエストを自由にオープンしてください。これをテーブルに持ってくれてありがとう!

関連する問題