Commit in DatabasePopulatorUtils if Connection has auto-commit=false
Prior to this commit, DatabasePopulatorUtils.execute(...) did not perform a commit for the current Connection. This works for most use cases; however, when DatabasePopulatorUtils is used to execute initialization scripts without a managed transaction -- for example, via a DataSourceInitializer configured as a bean in the ApplicationContext or via Spring Boot configuration in application.properties -- if the underlying database is configured with auto-commit=false, the results of executing the SQL scripts are not committed to the database which can lead to data being silently lost. This commit addresses this issue by committing the Connection for the supplied DataSource if the connection is not configured for auto-commit and is not transactional. Existing use cases running with a managed transaction should therefore not be affected by this change. Closes gh-27008
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -72,7 +72,8 @@ public abstract class DataSourceUtils {
|
||||
* @return a JDBC Connection from the given DataSource
|
||||
* @throws org.springframework.jdbc.CannotGetJdbcConnectionException
|
||||
* if the attempt to get a Connection failed
|
||||
* @see #releaseConnection
|
||||
* @see #releaseConnection(Connection, DataSource)
|
||||
* @see #isConnectionTransactional(Connection, DataSource)
|
||||
*/
|
||||
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
|
||||
try {
|
||||
@@ -298,6 +299,7 @@ public abstract class DataSourceUtils {
|
||||
* @param dataSource the DataSource that the Connection was obtained from
|
||||
* (may be {@code null})
|
||||
* @return whether the Connection is transactional
|
||||
* @see #getConnection(DataSource)
|
||||
*/
|
||||
public static boolean isConnectionTransactional(Connection con, @Nullable DataSource dataSource) {
|
||||
if (dataSource == null) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,9 +36,14 @@ public abstract class DatabasePopulatorUtils {
|
||||
|
||||
/**
|
||||
* Execute the given {@link DatabasePopulator} against the given {@link DataSource}.
|
||||
* <p>As of Spring Framework 5.3.11, the {@link Connection} for the supplied
|
||||
* {@code DataSource} will be {@linkplain Connection#commit() committed} if
|
||||
* it is not configured for {@link Connection#getAutoCommit() auto-commit} and
|
||||
* is not {@linkplain DataSourceUtils#isConnectionTransactional transactional}.
|
||||
* @param populator the {@code DatabasePopulator} to execute
|
||||
* @param dataSource the {@code DataSource} to execute against
|
||||
* @throws DataAccessException if an error occurs, specifically a {@link ScriptException}
|
||||
* @see DataSourceUtils#isConnectionTransactional(Connection, DataSource)
|
||||
*/
|
||||
public static void execute(DatabasePopulator populator, DataSource dataSource) throws DataAccessException {
|
||||
Assert.notNull(populator, "DatabasePopulator must not be null");
|
||||
@@ -47,6 +52,9 @@ public abstract class DatabasePopulatorUtils {
|
||||
Connection connection = DataSourceUtils.getConnection(dataSource);
|
||||
try {
|
||||
populator.populate(connection);
|
||||
if (!connection.getAutoCommit() && !DataSourceUtils.isConnectionTransactional(connection, dataSource)) {
|
||||
connection.commit();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
DataSourceUtils.releaseConnection(connection, dataSource);
|
||||
|
||||
Reference in New Issue
Block a user