2016-04-15 15 views
0

私はhibernate 3.6.4.Finalとsql server 2008 r2を使用しており、2000万を超えるレコードを持つテーブルに対してクエリを受け取りました。条件firstResult/maxResultを使用しているときにページング(結果100000〜100010の場合はselect top 100010 from ...)を実行すると、apiが不適正にサブオプティマナルクエリを生成するため、ネイティブSQLに戻しました。名前付きパラメータの主なパフォーマンスの低下とネイティブSQLでのhibernateを使用したSQLインジェクションの防止

このクエリは、SQL Studioで驚くほど速く実行されますが、名前付きパラメータまたは定位置パラメータを使用してこれらのクエリを冬眠させると痛みを伴います。 Google検索では解決策が見つかりませんでしたので、現在SQLインジェクションを許可するパラメータを連結していますが、これはもちろん生産のオプションではありません。

私が見落としたことがあるかどうか、または私が自分自身を圧延する前にパラメータを消毒するために使用することができ、おそらくいくつかの端をつかまえていないことに気づいていない少なくともいくつかの休止状態のAPIやライブラリがあるかどうかは疑問です。

String stringQuery ="select * from User as u where id = :id"; 

Query query=session.createQuery(stringQuery); 
query.setParameter("id",12); 

:..私は元の平均、

答えて

0

は残念ながら、基準APIは、SQLインジェクションを回避する最善の方法ですが、それは最善の方法は、動的パラメータで、通常の休止状態クエリを使用することで、とても遅いですまたは、新しいクラスMyQueryBuilderを作成してクエリをより動的にすることができます

setFirstResult`はあまりにも戻ってクエリを生成し、 `setMaxResults``経由で改ページをして:
public class myQueryBuilder(){ 

    public Query buildQuery(int id){ 
     String stringQuery ="select * from User as u where u.id = :id"; 
     Query query=session.createQuery(stringQuery); 
     query.setParameter("id",12); 
     return query; 
    } 

    public Query buildQuery(int id,String name){ 
     String stringQuery ="select * from User as u where u.id = :id and u.name = :name"; 
     Query query=session.createQuery(stringQuery); 
     query.setParameter("id",12); 
     query.setParameter("name",name); 
     return query; 
    } 

    ... 
//Later you can call the query builder methods as you want depending on your params 
} 

、それはsetParameterを使用を使用して、常に安全であることを覚えておいてください()メソッド

+0

HQLは基準を使用するのと同じ理由で不可能ですnoオプションをされて使用していませんとにかくほとんどのデータは破棄されます。例えば。 'setMaxResults(10)'と 'setFirstResult(100000)'はデータベースから100010のエントリをロードします: 'select top 100010 ...' –

+0

ページ付けをしたい場合:次のコードを使ってurクエリを実行しますString sqlString = myQueryBuilder.buildQuery (5).unwrap(org.hibernate.Query.class).getQueryString(); 次にconcat:sqlString + = "limit x、y"; –

+0

'limit'はMySQL固有であり、MS SQL Serverでは利用できません。同じテクニックは適用されません。なぜなら、ページングでは 'with X as(テーブルtからの行としてrow.number(order by ...)を選択します)select * from X where row> = xおよびrow < y'は、row_number関数をhibernate生成クエリに挿入し、外部クエリを追加する必要があります。 –

関連する問題