web-dev-qa-db-ja.com

Spring JDBCテンプレートで自動コミットをfalseに設定する方法

現在、以下のようにプロパティをデータソースBean IDに追加することにより、春にautocommitをfalseに設定しています:

   <property name="defaultAutoCommit" value="false" /> 

しかし、プロシージャを実行する前に、単一のJavaメソッドに具体的に追加する必要があります。以下のコードスニペットを使用しました。

  getJdbcTemplate().getDataSource().getConnection().setAutoCommit(false);

しかし、上記の行は自動コミットをfalseに設定していませんでしたか?
何か不足していますか?
または特定のJava springによるメソッドで自動コミットを設定する代替手段

ありがとう

20
bad programmer

問題は、Connectionで自動コミットを設定しているが、JdbcTemplateConnectionを覚えていないことです。代わりに、各操作に対して新しいConnectionを取得します。これは、Connection実装に応じて、同じDataSourceインスタンスである場合とそうでない場合があります。 defaultAutoCommitDataSourceのプロパティではないため、2つのオプションがあります。

  1. 具象データソースにdefaultAutoCommitのセッター(たとえば、 org.Apache.commons.dbcp.BasicDataSource )があると仮定して、DataSourceを具象実装にキャストします。もちろん、これは、Spring構成でDataSourceを変更できないことを意味します。これは、依存性注入の目的に反します。

((BasicDataSource)getJdbcTemplate().getDataSource()).setDefaultAutoCommit(false);

  1. 接続を取得するたびにAutoCommitをfalseに設定するラッパー実装にDataSourceを設定します。

    final DataSource ds = getJdbcTemplate().getDataSource();
    getJdbcTemplate().setDataSource(new DataSource(){
      // You'll need to implement all the methods, simply delegating to ds
    
      @Override
      public Connection getConnection() throws SQLException {
        Connection c = ds.getConnection();
        c.setAutoCommit(false);
        return c;
      }
    });
    
8
Yosef Weiner

現在の接続を取得する必要があります。例えば.

Connection conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
    try {
        conn.setAutoCommit(false);

        /**
         * Your Code
         */
        conn.commit();
    } catch (SQLException e) {
        conn.rollback();
        e.printStackTrace();
    }
2
Sujan

私はこれに出くわし、解決策は手遅れになっても誰かを助けるだろうと考えました。

Yosefが言ったように、getJdbcTemplate().getDataSource().getConnection()メソッドを呼び出して取得する接続は、操作のためのデータベースとの通信に使用される接続である場合とそうでない場合があります。

代わりに、データをコミットするのではなく、スクリプトをテストするだけでよい場合は、自動コミットをフォールトに設定したApache Commons DBCPデータソースを使用できます。 Beanの定義は次のとおりです。

/**
 * A datasource with auto commit set to false.
 */
@Bean
public DataSource dbcpDataSource() throws Exception {
    BasicDataSource ds = new BasicDataSource();
    ds.setUrl(url);
    ds.setUsername(username);
    ds.setPassword(password);
    ds.setDefaultAutoCommit(false);
    ds.setEnableAutoCommitOnReturn(false);
    return ds;
}

// Create either JdbcTemplate or NamedParameterJdbcTemplate as per your needs
@Bean
public NamedParameterJdbcTemplate dbcpNamedParameterJdbcTemplate() throws Exception {
    return new NamedParameterJdbcTemplate(dbcpDataSource());
}

そして、このような操作にはこのデータソースを使用します。

トランザクションをコミットする場合は、自動コミットをデフォルトの動作であるtrueに設定したデータソースのBeanをもう1つ用意することをお勧めします。

それが誰かを助けることを願っています!

1
Nagendra Varma

JdbcTemplateが実行するステートメントごとに実行する必要があります。 jdbcTemplate.execute()などごとに、データソースの接続プールから新しい接続を取得するためです。そのため、jdbcTemplateがそのクエリに使用する接続用に設定する必要があります。だからあなたは次のようなことをしなければなりません

 jdbcTemplate.execute("<your sql query", new PreparedStatementCallback<Integer>(){

        @Override
        public  Integer doInPreparedStatement(PreparedStatement stmt) throws SQLException, DataAccessException 
        {
            Connection cxn = stmt.getConnection();
            // set autocommit for that cxn object to false
            cxn.setAutoCommit(false);
            // set parameters etc in the stmt
            ....
            ....
            cxn.commit();
            // restore autocommit to true for that cxn object. because if the same object is obtained from the CxnPool later, autocommit will be false
            cxn.setAutoCommit(true);
            return 0;

        }
    });

お役に立てれば

1
Prabhu R

場合によっては、単に@Transactionalメソッド内、たとえばバッチ挿入の後、最後にコミットを実行します。

0
zhuguowei

私はこれをどこでも探していたので投稿しています:Springブートの設定プロパティを使用して、デフォルトの自動コミットモードを次のように設定しました:

spring.datasource.hikari.autocommit: false
0
moffeltje