Как установить autocommit в false в spring шаблоне jdbc
В настоящее время я устанавливаю autocommit в false в spring путем добавления свойства к идентификатору datasource bean, как показано ниже:
<property name="defaultAutoCommit" value="false" />
Но перед выполнением моей процедуры мне нужно добавить его специально в одном java-методе.
Я использовал приведенный ниже фрагмент кода.
getJdbcTemplate().getDataSource().getConnection().setAutoCommit(false);
Но вышеприведенная строка не устанавливала autoocommit в false?
Я что-то пропустил?
или любую альтернативу для установки autocommit в конкретном java-методе spring
Спасибо
Ответы
Ответ 1
Проблема в том, что вы устанавливаете autocommit для Connection
, но JdbcTemplate
не запоминает это Connection
; вместо этого он получает новое Connection
для каждой операции, и это может или не может быть одним и тем же экземпляром Connection
, в зависимости от вашей реализации DataSource
. Поскольку defaultAutoCommit
не является свойством DataSource
, у вас есть два варианта:
- Предполагая, что ваш конкретный источник данных имеет установщик для
defaultAutoCommit
(например, org.apache.commons.dbcp.BasicDataSource), defaultAutoCommit
DataSource
к конкретной реализации. Конечно, это означает, что вы больше не можете изменять свой DataSource
в конфигурации Spring, что противоречит цели внедрения зависимости.
((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;
}
});
Ответ 2
Вам нужно получить текущее соединение. например.
Connection conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
try {
conn.setAutoCommit(false);
/**
* Your Code
*/
conn.commit();
} catch (SQLException e) {
conn.rollback();
e.printStackTrace();
}
Ответ 3
Я только столкнулся с этим и думал, что решение поможет кому-то, даже если это слишком поздно.
Как сказал Йосеф, соединение, которое вы получаете, вызывая getJdbcTemplate().getDataSource().getConnection()
может или не может быть тем, которое используется для связи с базой данных для вашей операции.
Вместо этого, если ваше требование состоит в том, чтобы просто протестировать ваш сценарий, а не фиксировать данные, у вас может быть источник данных Apache Commons DBCP с автоматической фиксацией, установленной на ошибку. Определение бина дано ниже:
/**
* 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
что является поведением по умолчанию.
Надеюсь, это поможет кому-то!
Ответ 4
Вы должны будете сделать для каждого оператора, который выполняет 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;
}
});
Надеюсь это поможет
Ответ 5
В некоторых случаях вы можете просто добавить @Transactional
в метод, например, после некоторой пакетной вставки, выполните commit наконец.
Ответ 6
Я публикую это, потому что искал это везде: я использовал свойство конфигурации в Spring boot, чтобы добиться установки режима автоматической фиксации по умолчанию с помощью:
spring.datasource.hikari.autocommit: false