9

Hibernate で Spring Data JPA を使用する 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 でエンティティ プロパティを特別な並べ替えリクエスト パラメータとして定義できます。この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 クエリ文字を使用する可能性があることです。

たとえば、「noSuchProperty」でソートするように URL を変更した場合:

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 メソッドで が明示的に定義されているorg.hibernate.QueryException場合に発生する 3 番目の種類の例外もあります。)@Query

Spring Data JPA は、これらのパラメーターの並べ替え、ページング、および処理の詳細を抽象化します。ただし、これらのシナリオ (つまり、無効な並べ替えパラメーターが指定されている場合) を適切に処理していないようです。

追加のカスタム ロジックを追加して、エンティティに並べ替えプロパティが実際に存在することを検証できます。ただし、Spring Data JPA 抽象化の利点とシンプルさを失わないように、これを行うためのよりクリーンで集中化されたアプローチがあるかどうか疑問に思っています。この並べ替え機能はアプリ全体でさまざまなエンティティを使用して使用するため、要求されたすべてのエンティティ ページの並べ替えプロパティを明示的に定義または確認するのではなく、より一般的なアプローチが必要になるのが理想的です。

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

いくつかのアイデアと試み.. a を使用しQueryCreationListenerて、クエリの作成を傍受し、並べ替えパラメーターを取得できます。ただし、その時点でクエリを実際に変更することはできません。または、カスタムを拡張して使用することもできますPageableArgumentResolver(これは既に行っています)。並べ替えパラメーターを取得します。ただし、その時点でエンティティにアクセスすることも、エンティティが実際にその名前のプロパティを持っているかどうかを判断することもできません。サポートされているプロパティを明示的に宣言できます。ただし、繰り返しになりますが、これは、エンティティの特定または宣言された知識を必要とせずに、このシナリオを一元的かつ自動的に処理するという考えを無効にします。

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

4

2 に答える 2

3

私はコードを見ていましたが、スタック トレースがもう少し役立つと思います。しかし、私が見る限り、Spring コードを書き直したい場合は、2 つの場所に取り組む必要があると思います。

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

取り組むべき 2 番目の部分は、おそらくPageableArgumentResolver. 空の文字列または意味をなさないものを渡す場合、%20そのパラメーターは無視され、PageRequest.

幸せなハッキングと幸運。あなたの投稿を読んで、私のサイトが同じ問題に対して脆弱であり、良い解決策がないことに気付きました.

于 2012-10-16T16:06:21.807 に答える
1

PageableArgumentResolverこれらのシナリオを適切に処理できるように を改善すると思います。渡された asPropertyPathからインスタンスを作成しようとし、それが有効なものであることを確認します。デフォルトで単純に無効を削除することが理にかなっているかどうかについて、私は少し引き裂かれています。これにより、まったくソートされていない結果が返されます。これはおそらく最もシームレスなエクスペリエンスですが、結果がソートされない理由を突き止めるための退屈な試みにつながる可能性もあります。StringSortString

しかし、それ。Spring Data Commons に対してそのための JIRA チケットを作成し、このチケットをここにリンクするだけでよいと思います。実行可能な実装を具体化した場合は、気軽にプル リクエストを開いてください。これをすでにテーブルに持ってきてくれてありがとう!

于 2012-06-28T17:19:37.560 に答える