2012-08-28 22 views
5

Spring NamedParameterJdbcTemplateを使用して、テーブルからいくつかの値をフェッチしています。何らかの理由で、SQL Management Studioで同じクエリを実行するのではなく、Javaアプリケーションでクエリが非常に遅く実行されます。私もプロファイラに気付いた、準備されたステートメントは再利用されません。自分のJAVAアプリで同じクエリを複数回実行すると、異なる準備済みの文が実行されているのがわかります。だから、なぜステートメントが再利用されないのか分からない。 クエリでIN句を使用しているため、パフォーマンスが低下しますか?ここでSpring NamedParameterJDBCTemplateプリペアドステートメントの再利用

が私のJavaコードのサンプルSpringのNamedParameterJdbcTemplateのソースコードを見てみると

StringBuilder vQuery = new StringBuilder(); 
vQuery.append(" SELECT SUM(Qty) FROM vDemand"); 
vQuery.append(" WHERE ProductID = :ProductID"); 
vQuery.append(" AND [Date] >= :StartDate AND [Date] <= :EndDate"); 
vQuery.append(" AND CustomerID IN (:CustomerID)"); 

MapSqlParameterSource vNamedParameters = new MapSqlParameterSource(); 
vNamedParameters.addValue("ProductID", aProductID); 
vNamedParameters.addValue("CustomerID", aCustomerlIDs); 
vNamedParameters.addValue("StartDate", aDate, Types.TIMESTAMP); 
vNamedParameters.addValue("EndDate", aDate, Types.TIMESTAMP); 

int vTotalQuantity = this.getNamedParameterJdbcTemplate().queryForInt(vQuery.toString(), vNamedParameters); 
return vTotalQuantity; 

答えて

9

あり、それが構造ParsedSqlにあなたのSQLを解析し、その後、疑問符を使用して名前付きパラメータを置き換え、その後、PreparedStatementを構築し、あなたのパラメータでそれを埋める。

ParsedSqlエントリはキャッシュされますが、常に新しいPreparedStatementsが作成されるため、最終的にこれらはJDBCドライバレベルで再利用されません。

PreparedStatementは、通常のStatement以上の2つの利点があります。

  1. あなたはメソッドを使用しての代わりに、SQLクエリ自体の内部にそれをやってSQLにパラメータを追加します。これにより、SQLインジェクション攻撃を回避し、ドライバにタイプ変換をさせることができます。

  2. 同じように、PreparedStatementは異なるパラメータで呼び出すことができ、データベースエンジンはクエリ実行計画を再利用できます。

NamedParameterJdbcTemplateは、最初の利点をお手伝いしますが、後者は何もしません。

+0

ありがとうございます。私が見ている奇妙なことは、単一のクエリであっても、実行時間はSQL Server管理スタジオの実行時間の約50倍です。私は名前付きパラメータを取り除き、ストレートSQLが問題を修正するかどうかを調べるようにします。再度、感謝します。 – user320587

+2

これは別の問題だと思うので、jdbcドライバの設定を確認してください。ドライバと、クエリを実行するMainメソッドであるplain sqlを使用して、新しいプロジェクトを作成します。 50倍も遅いです。 – Luciano