Introduce constructors in ResourceDatabasePopulator

Issue: SPR-9531
This commit is contained in:
Sam Brannen 2014-03-13 13:45:05 +01:00
parent a006ca2542
commit 01b2f67f11
6 changed files with 138 additions and 171 deletions

View File

@ -39,6 +39,7 @@ import org.springframework.core.io.support.EncodedResource;
* @author Sam Brannen * @author Sam Brannen
* @author Chris Baldwin * @author Chris Baldwin
* @since 3.0 * @since 3.0
* @see DatabasePopulatorUtils
*/ */
public class ResourceDatabasePopulator implements DatabasePopulator { public class ResourceDatabasePopulator implements DatabasePopulator {
@ -59,6 +60,32 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
private boolean ignoreFailedDrops = false; private boolean ignoreFailedDrops = false;
/**
* Construct a new {@code ResourceDatabasePopulator} with default settings.
*/
public ResourceDatabasePopulator() {
/* no-op */
}
/**
* Construct a new {@code ResourceDatabasePopulator} with the supplied values.
*
* @param continueOnError flag to indicate that all failures in SQL should be
* logged but not cause a failure
* @param ignoreFailedDrops flag to indicate that a failed SQL {@code DROP}
* statement can be ignored
* @param sqlScriptEncoding the encoding for the supplied SQL scripts, if
* different from the platform encoding; may be {@code null}
* @param scripts the scripts to execute to populate the database
*/
public ResourceDatabasePopulator(boolean continueOnError, boolean ignoreFailedDrops, String sqlScriptEncoding,
Resource... scripts) {
this.continueOnError = continueOnError;
this.ignoreFailedDrops = ignoreFailedDrops;
this.sqlScriptEncoding = sqlScriptEncoding;
this.scripts = Arrays.asList(scripts);
}
/** /**
* Add a script to execute to populate the database. * Add a script to execute to populate the database.
* @param script the path to an SQL script * @param script the path to an SQL script
@ -77,8 +104,6 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
/** /**
* Specify the encoding for SQL scripts, if different from the platform encoding. * Specify the encoding for SQL scripts, if different from the platform encoding.
* <p>Note that setting this property has no effect on added scripts that are
* already {@linkplain EncodedResource encoded resources}.
* @see #addScript(Resource) * @see #addScript(Resource)
*/ */
public void setSqlScriptEncoding(String sqlScriptEncoding) { public void setSqlScriptEncoding(String sqlScriptEncoding) {
@ -145,18 +170,18 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
@Override @Override
public void populate(Connection connection) throws SQLException { public void populate(Connection connection) throws SQLException {
for (Resource script : this.scripts) { for (Resource script : this.scripts) {
ScriptUtils.executeSqlScript(connection, applyEncodingIfNecessary(script), this.continueOnError, ScriptUtils.executeSqlScript(connection, encodeScript(script), this.continueOnError,
this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter, this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter,
this.blockCommentEndDelimiter); this.blockCommentEndDelimiter);
} }
} }
private EncodedResource applyEncodingIfNecessary(Resource script) { /**
if (script instanceof EncodedResource) { * {@link EncodedResource} is not a sub-type of {@link Resource}. Thus we
return (EncodedResource) script; * always need to wrap each script resource in an encoded resource.
} */
else { private EncodedResource encodeScript(Resource script) {
return new EncodedResource(script, this.sqlScriptEncoding); return new EncodedResource(script, this.sqlScriptEncoding);
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,16 +16,16 @@
package org.springframework.jdbc.datasource.embedded; package org.springframework.jdbc.datasource.embedded;
import static org.junit.Assert.assertEquals;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.junit.Test; import org.junit.Test;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import static org.junit.Assert.*;
/** /**
* @author Keith Donald * @author Keith Donald
*/ */

View File

@ -22,6 +22,7 @@ import java.sql.SQLException;
import org.junit.After; import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.core.io.ClassRelativeResourceLoader; import org.springframework.core.io.ClassRelativeResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
@ -29,9 +30,8 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionSynchronizationManager;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*; import static org.mockito.Mockito.*;
/** /**
* @author Dave Syer * @author Dave Syer
@ -65,6 +65,18 @@ public class DatabasePopulatorTests {
} }
} }
private Resource resource(String path) {
return resourceLoader.getResource(path);
}
private Resource defaultSchema() {
return resource("db-schema.sql");
}
private Resource usersSchema() {
return resource("users-schema.sql");
}
@After @After
public void shutDown() { public void shutDown() {
if (TransactionSynchronizationManager.isSynchronizationActive()) { if (TransactionSynchronizationManager.isSynchronizationActive()) {
@ -75,178 +87,121 @@ public class DatabasePopulatorTests {
} }
@Test @Test
public void testBuildWithCommentsAndFailedDrop() throws Exception { public void buildWithCommentsAndFailedDrop() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema-failed-drop-comments.sql")); databasePopulator.addScript(resource("db-schema-failed-drop-comments.sql"));
databasePopulator.addScript(resourceLoader.getResource("db-test-data.sql")); databasePopulator.addScript(resource("db-test-data.sql"));
databasePopulator.setIgnoreFailedDrops(true); databasePopulator.setIgnoreFailedDrops(true);
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try {
databasePopulator.populate(connection);
}
finally {
connection.close();
}
assertTestDatabaseCreated(); assertTestDatabaseCreated();
} }
@Test @Test
public void testBuildWithNormalEscapedLiteral() throws Exception { public void buildWithNormalEscapedLiteral() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resourceLoader.getResource("db-test-data-escaped-literal.sql")); databasePopulator.addScript(resource("db-test-data-escaped-literal.sql"));
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try {
databasePopulator.populate(connection);
}
finally {
connection.close();
}
assertTestDatabaseCreated("'Keith'"); assertTestDatabaseCreated("'Keith'");
} }
@Test @Test
public void testBuildWithMySQLEscapedLiteral() throws Exception { public void buildWithMySQLEscapedLiteral() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resourceLoader.getResource("db-test-data-mysql-escaped-literal.sql")); databasePopulator.addScript(resource("db-test-data-mysql-escaped-literal.sql"));
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try {
databasePopulator.populate(connection);
}
finally {
connection.close();
}
assertTestDatabaseCreated("\\$Keith\\$"); assertTestDatabaseCreated("\\$Keith\\$");
} }
@Test @Test
public void testBuildWithMultipleStatements() throws Exception { public void buildWithMultipleStatements() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resourceLoader.getResource("db-test-data-multiple.sql")); databasePopulator.addScript(resource("db-test-data-multiple.sql"));
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try { assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class),
databasePopulator.populate(connection); equalTo(1));
} assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class),
finally { equalTo(1));
connection.close();
}
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), equalTo(1));
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), equalTo(1));
} }
@Test @Test
public void testBuildWithMultipleStatementsLongSeparator() throws Exception { public void buildWithMultipleStatementsLongSeparator() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resourceLoader.getResource("db-test-data-endings.sql")); databasePopulator.addScript(resource("db-test-data-endings.sql"));
databasePopulator.setSeparator("@@"); databasePopulator.setSeparator("@@");
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try { assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class),
databasePopulator.populate(connection); equalTo(1));
} assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class),
finally { equalTo(1));
connection.close();
}
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), equalTo(1));
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), equalTo(1));
} }
@Test @Test
public void testBuildWithMultipleStatementsWhitespaceSeparator() throws Exception { public void buildWithMultipleStatementsWhitespaceSeparator() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resourceLoader.getResource("db-test-data-whitespace.sql")); databasePopulator.addScript(resource("db-test-data-whitespace.sql"));
databasePopulator.setSeparator("/\n"); databasePopulator.setSeparator("/\n");
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try { assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class),
databasePopulator.populate(connection); equalTo(1));
} assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class),
finally { equalTo(1));
connection.close();
}
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), equalTo(1));
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), equalTo(1));
} }
@Test @Test
public void testBuildWithMultipleStatementsNewlineSeparator() throws Exception { public void buildWithMultipleStatementsNewlineSeparator() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resourceLoader.getResource("db-test-data-newline.sql")); databasePopulator.addScript(resource("db-test-data-newline.sql"));
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try { assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class),
databasePopulator.populate(connection); equalTo(1));
} assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class),
finally { equalTo(1));
connection.close();
}
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), equalTo(1));
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), equalTo(1));
} }
@Test @Test
public void testBuildWithMultipleStatementsMultipleNewlineSeparator() throws Exception { public void buildWithMultipleStatementsMultipleNewlineSeparator() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resourceLoader.getResource("db-test-data-multi-newline.sql")); databasePopulator.addScript(resource("db-test-data-multi-newline.sql"));
databasePopulator.setSeparator("\n\n"); databasePopulator.setSeparator("\n\n");
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try { assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class),
databasePopulator.populate(connection); equalTo(1));
} assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class),
finally { equalTo(1));
connection.close();
}
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), equalTo(1));
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), equalTo(1));
} }
@Test @Test
public void scriptWithEolBetweenTokens() throws Exception { public void scriptWithEolBetweenTokens() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("users-schema.sql")); databasePopulator.addScript(usersSchema());
databasePopulator.addScript(resourceLoader.getResource("users-data.sql")); databasePopulator.addScript(resource("users-data.sql"));
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try {
databasePopulator.populate(connection);
}
finally {
connection.close();
}
assertUsersDatabaseCreated("Brannen"); assertUsersDatabaseCreated("Brannen");
} }
@Test @Test
public void scriptWithCommentsWithinStatements() throws Exception { public void scriptWithCommentsWithinStatements() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("users-schema.sql")); databasePopulator.addScript(usersSchema());
databasePopulator.addScript(resourceLoader.getResource("users-data-with-comments.sql")); databasePopulator.addScript(resource("users-data-with-comments.sql"));
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(databasePopulator, db);
try {
databasePopulator.populate(connection);
}
finally {
connection.close();
}
assertUsersDatabaseCreated("Brannen", "Hoeller"); assertUsersDatabaseCreated("Brannen", "Hoeller");
} }
@Test @Test
public void testBuildWithSelectStatements() throws Exception { public void constructorWithMultipleScriptResources() throws Exception {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); final ResourceDatabasePopulator populator = new ResourceDatabasePopulator(false, false, null, usersSchema(),
databasePopulator.addScript(resourceLoader.getResource("db-test-data-select.sql")); resource("users-data-with-comments.sql"));
Connection connection = db.getConnection(); DatabasePopulatorUtils.execute(populator, db);
try { assertUsersDatabaseCreated("Brannen", "Hoeller");
databasePopulator.populate(connection); }
}
finally {
connection.close();
}
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), equalTo(1)); @Test
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), equalTo(1)); public void buildWithSelectStatements() throws Exception {
databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resource("db-test-data-select.sql"));
DatabasePopulatorUtils.execute(databasePopulator, db);
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class),
equalTo(1));
assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class),
equalTo(1));
} }
/** /**
@ -266,16 +221,9 @@ public class DatabasePopulatorTests {
*/ */
@Test(timeout = 1000) @Test(timeout = 1000)
public void executesHugeScriptInReasonableTime() throws SQLException { public void executesHugeScriptInReasonableTime() throws SQLException {
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); databasePopulator.addScript(defaultSchema());
databasePopulator.addScript(resourceLoader.getResource("db-test-data-huge.sql")); databasePopulator.addScript(resource("db-test-data-huge.sql"));
DatabasePopulatorUtils.execute(databasePopulator, db);
Connection connection = db.getConnection();
try {
databasePopulator.populate(connection);
}
finally {
connection.close();
}
} }
} }

View File

@ -23,6 +23,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
@ -184,11 +185,8 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst
*/ */
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException { protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
Resource resource = this.applicationContext.getResource(sqlResourcePath); Resource resource = this.applicationContext.getResource(sqlResourcePath);
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); DatabasePopulator databasePopulator = new ResourceDatabasePopulator(continueOnError, false,
databasePopulator.setContinueOnError(continueOnError); this.sqlScriptEncoding, resource);
databasePopulator.addScript(resource);
databasePopulator.setSqlScriptEncoding(this.sqlScriptEncoding);
DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource()); DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
} }

View File

@ -23,6 +23,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.TestExecutionListeners;
@ -175,11 +176,8 @@ public abstract class AbstractTransactionalTestNGSpringContextTests extends Abst
*/ */
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException { protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
Resource resource = this.applicationContext.getResource(sqlResourcePath); Resource resource = this.applicationContext.getResource(sqlResourcePath);
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); DatabasePopulator databasePopulator = new ResourceDatabasePopulator(continueOnError, false,
databasePopulator.setContinueOnError(continueOnError); this.sqlScriptEncoding, resource);
databasePopulator.addScript(resource);
databasePopulator.setSqlScriptEncoding(this.sqlScriptEncoding);
DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource()); DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
} }

View File

@ -29,6 +29,7 @@ import org.springframework.core.io.support.EncodedResource;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameterValue; import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.jdbc.datasource.init.ScriptUtils; import org.springframework.jdbc.datasource.init.ScriptUtils;
@ -220,11 +221,8 @@ public class JdbcTestUtils {
@Deprecated @Deprecated
public static void executeSqlScript(JdbcTemplate jdbcTemplate, EncodedResource resource, boolean continueOnError) public static void executeSqlScript(JdbcTemplate jdbcTemplate, EncodedResource resource, boolean continueOnError)
throws DataAccessException { throws DataAccessException {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); DatabasePopulator databasePopulator = new ResourceDatabasePopulator(continueOnError, false,
databasePopulator.setContinueOnError(continueOnError); resource.getEncoding(), resource.getResource());
databasePopulator.addScript(resource.getResource());
databasePopulator.setSqlScriptEncoding(resource.getEncoding());
DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource()); DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
} }