目前我通过向数据源bean id添加属性来在spring中将autocommit设置为false,如下所示:
<property name="defaultAutoCommit" value="false" />
但是我需要在执行我的程序之前在一个java方法中专门添加它。我使用了下面的代码片段。
getJdbcTemplate().getDataSource().getConnection().setAutoCommit(false);
但上面的一行并没有将autocommit设置为false? 我错过了什么吗? 或者通过spring在特定java方法中设置autocommit的任何替代方法
谢谢
问题是你在Connection
上设置autocommit,但是JdbcTemplate
不记得那个Connection
;相反,它为每个操作获得一个新的Connection
,这可能是也可能不是相同的Connection
实例,具体取决于你的DataSource
实现。由于defaultAutoCommit
不是DataSource
的财产,您有两种选择:
defaultAutoCommit
的setter(例如,org.apache.commons.dbcp.BasicDataSource),请将DataSource
强制转换为具体实现。当然,这意味着您不能再在Spring配置中更改DataSource
,这会破坏依赖注入的目的。((BasicDataSource)getJdbcTemplate().getDataSource()).setDefaultAutoCommit(false);
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;
}
});
您需要获取当前连接。例如
Connection conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
try {
conn.setAutoCommit(false);
/**
* Your Code
*/
conn.commit();
} catch (SQLException e) {
conn.rollback();
e.printStackTrace();
}
我刚刚遇到这个问题,并认为解决方案可以帮助某人,即使为时已晚。
正如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
,这是默认行为。
希望它可以帮到某人!
您必须为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;
}
});
希望这可以帮助
在某些情况下,您可以在方法中添加@Transactional
,例如在一些批量插入之后,最后执行commit。