From 49c9a2a9157861bad53ec47b67c8d821b0b4655a Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 4 Jun 2012 13:47:58 +0200 Subject: [PATCH] Use transactional connection during db population Previously, DatabasePopulatorUtils#execute looked up a Connection from the given DataSource directly which resulted in the executed statements not being executed against a transactional connection (if any) which in turn resulted in the statements executed by the populator potentially not being rolled back. Now DataSourceUtils#getConnection is used to transparently take part in any active transaction and #releaseConnection is used to ensure the connection is closed if appropriate. Issue: SPR-9457 --- .../init/DatabasePopulatorUtils.java | 15 ++++----- .../init/DatabasePopulatorTests.java | 33 ++++++++++++++++++- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java index 0cf2318285..1f046d07d2 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -17,16 +17,18 @@ package org.springframework.jdbc.datasource.init; import java.sql.Connection; -import java.sql.SQLException; + import javax.sql.DataSource; import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.util.Assert; /** * Utility methods for executing a DatabasePopulator. * * @author Juergen Hoeller + * @author Oliver Gierke * @since 3.1 */ public abstract class DatabasePopulatorUtils { @@ -40,16 +42,13 @@ public abstract class DatabasePopulatorUtils { Assert.notNull(populator, "DatabasePopulator must be provided"); Assert.notNull(dataSource, "DataSource must be provided"); try { - Connection connection = dataSource.getConnection(); + Connection connection = DataSourceUtils.getConnection(dataSource); try { populator.populate(connection); } finally { - try { - connection.close(); - } - catch (SQLException ex) { - // ignore + if (connection != null) { + DataSourceUtils.releaseConnection(connection, dataSource); } } } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java index 04d59698cc..e119fee5c8 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 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. @@ -19,17 +19,24 @@ package org.springframework.jdbc.datasource.init; import static org.junit.Assert.assertEquals; import java.sql.Connection; +import java.sql.SQLException; + +import org.easymock.EasyMock; import org.junit.After; import org.junit.Test; + import org.springframework.core.io.ClassRelativeResourceLoader; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.transaction.support.TransactionSynchronizationManager; /** * @author Dave Syer * @author Sam Brannen + * @author Oliver Gierke */ public class DatabasePopulatorTests { @@ -54,6 +61,12 @@ public class DatabasePopulatorTests { @After public void shutDown() { + + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.clear(); + TransactionSynchronizationManager.unbindResource(db); + } + db.shutdown(); } @@ -207,4 +220,22 @@ public class DatabasePopulatorTests { assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Dave'")); } + /** + * @see SPR-9457 + */ + @Test + public void usesBoundConnectionIfAvailable() throws SQLException { + + TransactionSynchronizationManager.initSynchronization(); + Connection connection = DataSourceUtils.getConnection(db); + + DatabasePopulator populator = EasyMock.createMock(DatabasePopulator.class); + populator.populate(connection); + EasyMock.expectLastCall(); + EasyMock.replay(populator); + + DatabasePopulatorUtils.execute(populator, db); + + EasyMock.verify(populator); + } }