2009-06-08 8 views
6

many reasonsのために準備されたステートメントを使用したいと思います。言い換えればPreparedStatementsを作成するために接続が必要なのはなぜですか?

/* This opens a connection, executes the query, and closes the connection */ 
public static void executeNonQuery(String queryString); 

が、私は唯一のクエリを策定し、パラメータで養うために持っている私のアプリケーションロジックをしたいが、接続&文に対処ません: しかし、私はこのように見えるメソッドを作成したいです。しかし、PreparedStatementsは接続オブジェクトから作成されるので、現在String.format()を使用してクエリ文字列を準備しています。

String.format()を使用せずにしたいことを行う方法はありますか?

+0

executeNonQueryメソッドには1つの問題があります。接続を取得することです。このメソッドを実行するたびに作成すると、パフォーマンスの問題が何度も繰り返し実行されます(接続の作成と終了は高価です)。これが、最初の呼び出しでのみ接続を作成するオブジェクトにカプセル化されている場合は、問題が発生します。多分時間に基づいていますか?キャッシュに静的フィールドを使用する場合は、これが収集されないように注意してください。ただし、接続をキャッシュする際には同時呼び出しに注意してください。ロック機構(syncrhonizedなど)を使用しないと、多くの接続が作成される可能性があります。 –

答えて

14

なぜPreparedStatementsを作成する必要がありますか?

ステートメントは、接続ごとに大部分RDBMSで用意されているためです。

プリペアドステートメントは、実際にはアクセス許可、エンコード、照合設定などを考慮しないキャッシュプランです。

これはすべてクエリの解析中に行われます。

私が欲しいものを行う方法は、あなたがここにString.format()を必要とする理由を参照しないでください

String.format()を使用せずにあります。

クエリをクラスとして実装し、接続を作成してクラスコンストラクタでクエリを準備し、メソッドで実行することができます。バインドされたパラメータは、クエリの実行中に?年代に代入されます

SELECT * 
FROM table 
WHERE col1 = ? 
     AND col2 = ? 

、:

パラメータ化クエリは、一般的に次のようになります。

  • static接続ハンドルを作成します:あなたはstaticメソッドを使用する場合は

  • パラメータ化されたクエリテキストをkeyとし、準備クエリのハンドルをvalueとして使用して、準備クエリのハッシュテーブルを作成します(static)。
  • クエリを実行するときはいつでも、そのハンドルを見つけて(見つからなければ作成する)、パラメータをバインドしてクエリを実行するために使用します。
1

「アプリケーション」ロジックで、作成したデータレイヤーを使用して、そのようなインターフェイスメソッドを提示できないのはなぜですか?

あなたのデータレイヤーは、そのexecuteNonQueryメソッド内で、接続の作成、文の準備などを処理できます。

クエリ/ステートメントのパラメータを自分自身を文字列にマージしようとすると、足で自分自身を撮影し、実際にはPreparedStatementsのパラメータ機能を使用していないと思います。なぜあなたはこれをしたいと思うのか分かりません。

SpringのようなAPIを使用すると、接続の処理をすべて抽象化できる一連のJdbcTemplateクラスがありますが、Mapのパラメータで作業することもできます。

0

sqlをとるexecuteメソッドと、パラメータを表すオブジェクトのリストと、ResultSetを処理するオブジェクトを持つQueryRunnerを呼び出すクラスを持つことによって、JDBCのすべてを抽象化します。 JDBCからsetObjectメソッドを使用してパラメータを設定すると、基になるオブジェクトに基づいて使用する適切なDBタイプがわかります。ここに私のコードの一部があります。私はこれを包む別の方法を持っており、接続を取得します。

public void executeNoCommit(Connection conn, 
          String sql, 
          List params, 
          ResultSetProcessor processor) throws SQLException { 
    PreparedStatement stmt = null; 
    ResultSet rs = null; 
    int updateCount = 0; 
    Iterator it; 
    int paramIndex = 1; 
    boolean query; 

    try { 
     stmt = conn.prepareStatement(sql); 

     if (params != null) { 
      it = params.iterator(); 
      while (it.hasNext()) { 
       stmt.setObject(paramIndex, it.next()); 
       paramIndex++; 
      } 
     } 

     query = stmt.execute(); 
     if (query) { 
      rs = stmt.getResultSet(); 
     } 
     else { 
      updateCount = stmt.getUpdateCount(); 
     } 

     processor.process(rs, updateCount); 
    } 
    finally { 
     if (rs != null) { 
      try { 
       rs.close(); 
      } 
      catch (SQLException e) { 
       log.error(e); 
      } 
     } 

     if (stmt != null) { 
      try { 
       stmt.close(); 
      } 
      catch (SQLException e) { 
       log.error(e); 
      } 
     } 
    } 
} 
+0

コードを投稿できますか? – ripper234

0

あなたはおそらくApacheのCommonsのライブラリにDbUtilsパッケージのような何かをしたい:[http://commons.apache.org/dbutils/index.html][1]

QueryRunnerクラスを使用すると、手動でのPreparedStatementを作成することなく、SQL文を実行し、あるいはそのためのオープンな接続を持っていることができます問題。例のページから:

QueryRunner run = new QueryRunner(dataSource); 
try 
{ 
    // Create an object array to hold the values to insert 
    Object[] insertParams = {"John Doe", new Double(1.82)}; 
    // Execute the SQL update statement and return the number of 
    // inserts that were made 
    int inserts = run.update("INSERT INTO Person (name,height) VALUES (?,?)", 
           insertParams); 

    // Now it's time to rise to the occation... 
    Object[] updateParams = {new Double(2.05), "John Doe"}; 
    int updates = run.update("UPDATE Person SET height=? WHERE name=?", 
           updateParams); 
} 
catch(SQLException sqle) { 
    // Handle it 
} 

だから、基本的に透過的に準備された文の作成を処理し、あなたが本当に知っておく必要がある唯一のものは、DataSourceです。これはupdate/insert以外のステートメント、つまりplain-vanilla selectクエリでも同様に機能し、ResultSetHandlerを作成すると、完全に準備されたBeanやキー付きのMapにResultSetを変換する機能が得られます列名であり、値は実際の行の値です。 ORMソリューション全体を実装できない場合に非常に便利です。

関連する問題