如何在spring jdbc模板中将autocommit设置为false

时间:2014-08-08 07:07:51

标签: spring spring-mvc spring-jdbc spring-transactions

目前我在Spring中通过向数据源bean ID添加属性来将autocommit设置为false,如下所示:

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

但是我需要在执行我的程序之前在一个java方法中专门添加它。 我使用了下面的代码片段。

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

但是上面这行没有将autocommit设置为false?
我错过了什么吗?
或者通过spring

在特定java方法中设置autocommit的任何替代方法

由于

7 个答案:

答案 0 :(得分:5)

问题是您要在Connection上设置自动提交,但JdbcTemplate并不记得Connection;相反,它为每个操作获取一个新的Connection,可能是也可能不是同一个Connection实例,具体取决于您的DataSource实现。由于defaultAutoCommit不是DataSource上的属性,因此您有两种选择:

  1. 假设您的具体数据源具有defaultAutoCommit的setter(例如,org.apache.commons.dbcp.BasicDataSource),请将DataSource强制转换为具体实现。当然,这意味着您无法再更改Spring配置中的DataSource,这会破坏依赖注入的目的。
  2. ((BasicDataSource)getJdbcTemplate().getDataSource()).setDefaultAutoCommit(false);

    1. DataSource设置为每次获取连接时将AutoCommit设置为false的包装器实现。

      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;
        }
      });
      

答案 1 :(得分:1)

您需要获取当前连接。 e.g。

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

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

答案 2 :(得分:1)

我刚刚遇到过这个问题,并认为解决方案可以帮助某人,即使为时已晚。

正如Yosef所说,通过调用getJdbcTemplate().getDataSource().getConnection()方法获得的连接可能是也可能不是用于与数据库进行通信的连接。

相反,如果您的要求是仅测试脚本而不是提交数据,则可以将Apache Commons DBCP数据源与自动提交设置为fault。 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());
}

并将此数据源用于任何此类操作。

如果您希望提交事务,我建议您再添加一个数据源bean,并将自动提交设置为true,这是默认行为。

希望它有所帮助!

答案 3 :(得分:1)

您必须为jdbcTemplate执行的每个语句执行操作。因为对于每个jdbcTemplate.execute()等,它从Datasource的连接池获得一个新连接。因此,您必须为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;

        }
    });

希望这有帮助

答案 4 :(得分:0)

在某些情况下,您只需在方法中添加@Transactional,例如批量插入后,最后执行提交。

答案 5 :(得分:0)

我之所以发布此内容,是因为我到处都在寻找它:我在Spring Boot中使用configuration属性通过以下方式实现设置默认的自动提交模式:

spring.datasource.hikari.autocommit: false

答案 6 :(得分:0)

5年后仍然是一个有效的问题,我以这种方式解决了我的问题:

  1. 使用connection.setAutoCommit(false);设置连接。
  2. 使用该连接创建一个jbc模板;
  3. 做好您的工作并投入。
    Connection connection = dataSource.getConnection();
    connection.setAutoCommit(false);
    JdbcTemplate jdbcTemplate = 
    new  JdbcTemplate(newSingleConnectionDataSource(connection, true));
    // ignore case in mapping result
    jdbcTemplate.setResultsMapCaseInsensitive(true);
    // do your stuff
    connection.commit();