38

JDBC テンプレートを使用しており、準備済みステートメントを使用してデータベースから読み取りたいと考えています。.csv ファイルの多くの行を繰り返し処理し、すべての行で、対応する値を使用していくつかの SQL 選択クエリを実行します。

データベースからの読み取りを高速化したいのですが、JDBC テンプレートをプリペアド ステートメントで動作させる方法がわかりません。

PreparedStatementCreatorPreparedStatementSetterがあります。この例のように、両方とも匿名の内部クラスで作成されます。しかし、PreparedStatementSetter クラス内では、準備済みステートメントで設定したい値にアクセスできません。

私は.csvファイルを繰り返し処理しているので、それらを知らないため、それらを文字列としてハードコーディングすることはできません。また、コンストラクターの引数がないため、PreparedStatementSetter に渡すこともできません。また、値を final に設定するのもばかげています。

私は、準備済みステートメントの作成がかなり単純であることに慣れていました。何かのようなもの

PreparedStatement updateSales = con.prepareStatement(
    "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75); 
updateSales.setString(2, "Colombian"); 
updateSales.executeUpdate():

このJava チュートリアルのように。

4

5 に答える 5

37

フォームを使用するだけの場合、既定では、は内部でJDBCTemplate独自の処理を行います。Spring とデータベースがコンパイルされたクエリを管理するので、開く、閉じる、リソース保護などについて心配する必要はありません。Spring の利点の 1 つです。これに関する Spring 2.5 のドキュメントへのリンク。それが物事をより明確にすることを願っています。また、少なくとも一部の Oracle の JDBC ドライバーの場合と同様に、ステートメントのキャッシュは JDBC レベルで行うことができます。 それは私が有能にできるよりもはるかに詳細になります。PreparedStatement.update(String sql, Object ... args)

于 2010-06-07T13:58:22.200 に答える
19
class Main {
    public static void main(String args[]) throws Exception {
        ApplicationContext ac = new
          ClassPathXmlApplicationContext("context.xml", Main.class);
        DataSource dataSource = (DataSource) ac.getBean("dataSource");
// DataSource mysqlDataSource = (DataSource) ac.getBean("mysqlDataSource");

        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        String prasobhName = 
        jdbcTemplate.query(
           "select first_name from customer where last_name like ?",
            new PreparedStatementSetter() {
              public void setValues(PreparedStatement preparedStatement) throws
                SQLException {
                  preparedStatement.setString(1, "nair%");
              }
            }, 
            new ResultSetExtractor<Long>() {
              public Long extractData(ResultSet resultSet) throws SQLException,
                DataAccessException {
                  if (resultSet.next()) {
                      return resultSet.getLong(1);
                  }
                  return null;
              }
            }
        );
        System.out.println(machaceksName);
    }
}
于 2011-02-11T10:11:57.160 に答える
9

次のことを試してください。

PreparedStatementCreator creator = new PreparedStatementCreator() {
    @Override
    public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
        PreparedStatement updateSales = con.prepareStatement(
        "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
        updateSales.setInt(1, 75); 
        updateSales.setString(2, "Colombian"); 
        return updateSales;
    }
};
于 2010-06-07T12:18:56.033 に答える
3

プリペアドステートメントの処理を少なくともメソッドに除外します。この場合、結果がないため、かなり単純です(そして、接続が変更されないインスタンス変数であると仮定します)。

private PreparedStatement updateSales;
public void updateSales(int sales, String cof_name) throws SQLException {
    if (updateSales == null) {
        updateSales = con.prepareStatement(
            "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");
    }
    updateSales.setInt(1, sales);
    updateSales.setString(2, cof_name);
    updateSales.executeUpdate();
}

その時点で、それはただ呼び出すことの問題です:

updateSales(75, "Colombian");

他のものと統合するのはとても簡単ですよね?また、メソッドを何度も呼び出すと、更新は1回だけ作成されるため、処理が大幅に高速化されます。さて、あなたが独自のトランザクションで各更新を行うようなクレイジーなことをしないと仮定すると...

タイプが固定されていることに注意してください。これは、特定のクエリ/更新について、データベースがその仕事を効率的に実行できるように修正する必要があるためです。CSVファイルから任意の文字列を取得するだけの場合は、それらを文字列として渡します。ロックもありません。代わりに、個々の接続を単一のスレッドから使​​用するように維持する方がはるかに優れています。

于 2010-06-07T12:36:34.050 に答える
2

を使用して select ステートメントを試してみましたPreparedStatementが、Jdbc テンプレートよりも高速ではないことが判明しました。おそらく、mezmo が示唆したように、準備済みステートメントが自動的に作成されます。

とにかく、私の sql が非常に遅い理由SELECTは別のものでした。このWHERE句でLIKEは、完全一致を見つけることだけが目的だったときに、常に operator を使用しました。私が見つけたようLIKEに、パターンの検索は非常に遅いです。

=現在、オペレーターを使用していますが、はるかに高速です。

于 2010-06-08T09:28:27.470 に答える