diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java index f43a42304d..68918f5150 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java @@ -26,6 +26,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.core.io.Resource; import org.springframework.core.io.support.EncodedResource; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -53,6 +54,13 @@ public abstract class ScriptUtils { */ public static final String DEFAULT_STATEMENT_SEPARATOR = ";"; + /** + * Fallback statement separator within SQL scripts. + *
Used if neither a custom defined separator nor the + * {@link #DEFAULT_STATEMENT_SEPARATOR} is present in a given script. + */ + public static final String FALLBACK_STATEMENT_SEPARATOR = "\n"; + /** * Default prefix for line comments within SQL scripts. */ @@ -78,7 +86,7 @@ public abstract class ScriptUtils { /** * Split an SQL script into separate statements delimited by the provided - * delimiter character. Each individual statement will be added to the + * separator character. Each individual statement will be added to the * provided {@code List}. *
Within the script, {@value #DEFAULT_COMMENT_PREFIX} will be used as the
* comment prefix; any text beginning with the comment prefix and extending to
@@ -89,18 +97,41 @@ public abstract class ScriptUtils {
* in a block comment will be omitted from the output. In addition, multiple
* adjacent whitespace characters will be collapsed into a single space.
* @param script the SQL script
- * @param delimiter character delimiting each statement — typically a ';' character
+ * @param separator character separating each statement — typically a ';'
* @param statements the list that will contain the individual statements
+ * @see #splitSqlScript(String, String, List)
* @see #splitSqlScript(EncodedResource, String, String, String, String, String, List)
*/
- public static void splitSqlScript(String script, char delimiter, List Within the script, {@value #DEFAULT_COMMENT_PREFIX} will be used as the
+ * comment prefix; any text beginning with the comment prefix and extending to
+ * the end of the line will be omitted from the output. Similarly,
+ * {@value #DEFAULT_BLOCK_COMMENT_START_DELIMITER} and
+ * {@value #DEFAULT_BLOCK_COMMENT_END_DELIMITER} will be used as the
+ * start and end block comment delimiters: any text enclosed
+ * in a block comment will be omitted from the output. In addition, multiple
+ * adjacent whitespace characters will be collapsed into a single space.
+ * @param script the SQL script
+ * @param separator text separating each statement — typically a ';' or newline character
+ * @param statements the list that will contain the individual statements
+ * @see #splitSqlScript(String, char, List)
+ * @see #splitSqlScript(EncodedResource, String, String, String, String, String, List)
+ */
+ public static void splitSqlScript(String script, String separator, List Within the script, the provided {@code commentPrefix} will be honored:
* any text beginning with the comment prefix and extending to the end of the
@@ -111,8 +142,8 @@ public abstract class ScriptUtils {
* will be collapsed into a single space.
* @param resource the resource from which the script was read
* @param script the SQL script; never {@code null} or empty
- * @param delimiter text delimiting each statement — typically a ';'
- * character; never {@code null}
+ * @param separator text separating each statement — typically a ';' or
+ * newline character; never {@code null}
* @param commentPrefix the prefix that identifies SQL line comments —
* typically "--"; never {@code null} or empty
* @param blockCommentStartDelimiter the start block comment delimiter;
@@ -121,12 +152,12 @@ public abstract class ScriptUtils {
* never {@code null} or empty
* @param statements the list that will contain the individual statements
*/
- public static void splitSqlScript(EncodedResource resource, String script, String delimiter, String commentPrefix,
+ public static void splitSqlScript(EncodedResource resource, String script, String separator, String commentPrefix,
String blockCommentStartDelimiter, String blockCommentEndDelimiter, List Lines beginning with the comment prefix are excluded from the
* results; however, line comments anywhere else — for example, within
* a statement — will be included in the results.
@@ -258,8 +288,7 @@ public abstract class ScriptUtils {
String currentStatement = lineNumberReader.readLine();
StringBuilder scriptBuilder = new StringBuilder();
while (currentStatement != null) {
- if (StringUtils.hasText(currentStatement)
- && (commentPrefix != null && !currentStatement.startsWith(commentPrefix))) {
+ if (commentPrefix != null && !currentStatement.startsWith(commentPrefix)) {
if (scriptBuilder.length() > 0) {
scriptBuilder.append('\n');
}
@@ -267,11 +296,11 @@ public abstract class ScriptUtils {
}
currentStatement = lineNumberReader.readLine();
}
- maybeAddSeparatorToScript(scriptBuilder, separator);
+ appendSeparatorToScriptIfNecessary(scriptBuilder, separator);
return scriptBuilder.toString();
}
- private static void maybeAddSeparatorToScript(StringBuilder scriptBuilder, String separator) {
+ private static void appendSeparatorToScriptIfNecessary(StringBuilder scriptBuilder, String separator) {
if (separator == null) {
return;
}
@@ -305,6 +334,48 @@ public abstract class ScriptUtils {
return false;
}
+ /**
+ * Execute the given SQL script using default settings for separator separators,
+ * comment delimiters, and exception handling flags.
+ * Statement separators and comments will be removed before executing
+ * individual statements within the supplied script.
+ * Do not use this method to execute DDL if you expect rollback.
+ * @param connection the JDBC connection to use to execute the script; already
+ * configured and ready to use
+ * @param resource the resource to load the SQL script from; encoded with the
+ * current platform's default encoding
+ * @see #executeSqlScript(Connection, EncodedResource, boolean, boolean, String, String, String, String)
+ * @see #DEFAULT_COMMENT_PREFIX
+ * @see #DEFAULT_STATEMENT_SEPARATOR
+ * @see #DEFAULT_BLOCK_COMMENT_START_DELIMITER
+ * @see #DEFAULT_BLOCK_COMMENT_END_DELIMITER
+ */
+ public static void executeSqlScript(Connection connection, Resource resource) throws SQLException, ScriptException {
+ executeSqlScript(connection, new EncodedResource(resource));
+ }
+
+ /**
+ * Execute the given SQL script using default settings for separator separators,
+ * comment delimiters, and exception handling flags.
+ * Statement separators and comments will be removed before executing
+ * individual statements within the supplied script.
+ * Do not use this method to execute DDL if you expect rollback.
+ * @param connection the JDBC connection to use to execute the script; already
+ * configured and ready to use
+ * @param resource the resource (potentially associated with a specific encoding)
+ * to load the SQL script from
+ * @see #executeSqlScript(Connection, EncodedResource, boolean, boolean, String, String, String, String)
+ * @see #DEFAULT_COMMENT_PREFIX
+ * @see #DEFAULT_STATEMENT_SEPARATOR
+ * @see #DEFAULT_BLOCK_COMMENT_START_DELIMITER
+ * @see #DEFAULT_BLOCK_COMMENT_END_DELIMITER
+ */
+ public static void executeSqlScript(Connection connection, EncodedResource resource) throws SQLException,
+ ScriptException {
+ executeSqlScript(connection, resource, false, false, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR,
+ DEFAULT_BLOCK_COMMENT_START_DELIMITER, DEFAULT_BLOCK_COMMENT_END_DELIMITER);
+ }
+
/**
* Execute the given SQL script.
* Statement separators and comments will be removed before executing
@@ -321,7 +392,8 @@ public abstract class ScriptUtils {
* @param commentPrefix the prefix that identifies comments in the SQL script —
* typically "--"
* @param separator the script statement separator; defaults to
- * {@value #DEFAULT_STATEMENT_SEPARATOR} if not specified
+ * {@value #DEFAULT_STATEMENT_SEPARATOR} if not specified and falls back to
+ * {@value #FALLBACK_STATEMENT_SEPARATOR} as a last resort
* @param blockCommentStartDelimiter the start block comment delimiter; never
* {@code null} or empty
* @param blockCommentEndDelimiter the end block comment delimiter; never
@@ -346,9 +418,9 @@ public abstract class ScriptUtils {
if (separator == null) {
separator = DEFAULT_STATEMENT_SEPARATOR;
- if (!containsSqlScriptDelimiters(script, separator)) {
- separator = "\n";
- }
+ }
+ if (!containsSqlScriptDelimiters(script, separator)) {
+ separator = FALLBACK_STATEMENT_SEPARATOR;
}
splitSqlScript(resource, script, separator, commentPrefix, blockCommentStartDelimiter,
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabaseInitializationTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabaseInitializationTests.java
new file mode 100644
index 0000000000..7d85f92cb2
--- /dev/null
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabaseInitializationTests.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.jdbc.datasource.init;
+
+import org.junit.After;
+import org.junit.Before;
+import org.springframework.core.io.ClassRelativeResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * Abstract base class for integration tests involving database initialization.
+ *
+ * @author Sam Brannen
+ * @since 4.0.3
+ */
+public abstract class AbstractDatabaseInitializationTests {
+
+ private final ClassRelativeResourceLoader resourceLoader = new ClassRelativeResourceLoader(getClass());
+
+ protected EmbeddedDatabase db;
+ protected JdbcTemplate jdbcTemplate;
+
+
+ @Before
+ public void setUp() {
+ db = new EmbeddedDatabaseBuilder().setType(getEmbeddedDatabaseType()).build();
+ jdbcTemplate = new JdbcTemplate(db);
+ }
+
+ @After
+ public void shutDown() {
+ if (TransactionSynchronizationManager.isSynchronizationActive()) {
+ TransactionSynchronizationManager.clear();
+ TransactionSynchronizationManager.unbindResource(db);
+ }
+ db.shutdown();
+ }
+
+ protected abstract EmbeddedDatabaseType getEmbeddedDatabaseType();
+
+ protected Resource resource(String path) {
+ return resourceLoader.getResource(path);
+ }
+
+}
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/AbstractDatabasePopulatorTests.java
similarity index 89%
rename from spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java
rename to spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabasePopulatorTests.java
index 571b744384..f26116b54a 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/AbstractDatabasePopulatorTests.java
@@ -19,14 +19,9 @@ package org.springframework.jdbc.datasource.init;
import java.sql.Connection;
import java.sql.SQLException;
-import org.junit.After;
import org.junit.Test;
-import org.springframework.core.io.ClassRelativeResourceLoader;
import org.springframework.core.io.Resource;
-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;
import static org.hamcrest.Matchers.*;
@@ -34,57 +29,16 @@ import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
+ * Abstract base class for integration tests for {@link ResourceDatabasePopulator}.
+ *
* @author Dave Syer
* @author Sam Brannen
* @author Oliver Gierke
*/
-public class DatabasePopulatorTests {
-
- private final EmbeddedDatabase db = new EmbeddedDatabaseBuilder().build();
+public abstract class AbstractDatabasePopulatorTests extends AbstractDatabaseInitializationTests {
private final ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
- private final ClassRelativeResourceLoader resourceLoader = new ClassRelativeResourceLoader(getClass());
-
- private final JdbcTemplate jdbcTemplate = new JdbcTemplate(db);
-
-
- private void assertTestDatabaseCreated() {
- assertTestDatabaseCreated("Keith");
- }
-
- private void assertTestDatabaseCreated(String name) {
- assertEquals(name, jdbcTemplate.queryForObject("select NAME from T_TEST", String.class));
- }
-
- private void assertUsersDatabaseCreated(String... lastNames) {
- for (String lastName : lastNames) {
- assertThat("Did not find user with last name [" + lastName + "].",
- jdbcTemplate.queryForObject("select count(0) from users where last_name = ?", Integer.class, lastName),
- equalTo(1));
- }
- }
-
- 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
- public void shutDown() {
- if (TransactionSynchronizationManager.isSynchronizationActive()) {
- TransactionSynchronizationManager.clear();
- TransactionSynchronizationManager.unbindResource(db);
- }
- db.shutdown();
- }
@Test
public void buildWithCommentsAndFailedDrop() throws Exception {
@@ -226,4 +180,28 @@ public class DatabasePopulatorTests {
DatabasePopulatorUtils.execute(databasePopulator, db);
}
+ private void assertTestDatabaseCreated() {
+ assertTestDatabaseCreated("Keith");
+ }
+
+ private void assertTestDatabaseCreated(String name) {
+ assertEquals(name, jdbcTemplate.queryForObject("select NAME from T_TEST", String.class));
+ }
+
+ private void assertUsersDatabaseCreated(String... lastNames) {
+ for (String lastName : lastNames) {
+ assertThat("Did not find user with last name [" + lastName + "].",
+ jdbcTemplate.queryForObject("select count(0) from users where last_name = ?", Integer.class, lastName),
+ equalTo(1));
+ }
+ }
+
+ private Resource defaultSchema() {
+ return resource("db-schema.sql");
+ }
+
+ private Resource usersSchema() {
+ return resource("users-schema.sql");
+ }
+
}
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/H2DatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/H2DatabasePopulatorTests.java
new file mode 100644
index 0000000000..699ea75b1a
--- /dev/null
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/H2DatabasePopulatorTests.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2002-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.jdbc.datasource.init;
+
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+
+/**
+ * @author Sam Brannen
+ * @since 4.0.3
+ */
+public class H2DatabasePopulatorTests extends AbstractDatabasePopulatorTests {
+
+ protected EmbeddedDatabaseType getEmbeddedDatabaseType() {
+ return EmbeddedDatabaseType.H2;
+ }
+
+}
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/HsqlDatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/HsqlDatabasePopulatorTests.java
new file mode 100644
index 0000000000..9ab79b6054
--- /dev/null
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/HsqlDatabasePopulatorTests.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2002-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.jdbc.datasource.init;
+
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+
+/**
+ * @author Sam Brannen
+ * @since 4.0.3
+ */
+public class HsqlDatabasePopulatorTests extends AbstractDatabasePopulatorTests {
+
+ protected EmbeddedDatabaseType getEmbeddedDatabaseType() {
+ return EmbeddedDatabaseType.HSQL;
+ }
+
+}
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java
new file mode 100644
index 0000000000..f7d8f18092
--- /dev/null
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.jdbc.datasource.init;
+
+import java.sql.SQLException;
+
+import org.junit.Test;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Integration tests for {@link ScriptUtils}.
+ *
+ * @author Sam Brannen
+ * @see ScriptUtilsUnitTests
+ * @since 4.0.3
+ */
+public class ScriptUtilsIntegrationTests extends AbstractDatabaseInitializationTests {
+
+ protected EmbeddedDatabaseType getEmbeddedDatabaseType() {
+ return EmbeddedDatabaseType.HSQL;
+ }
+
+ @Test
+ public void executeSqlScript() throws SQLException {
+ ScriptUtils.executeSqlScript(db.getConnection(), resource("users-schema.sql"));
+ ScriptUtils.executeSqlScript(db.getConnection(), resource("test-data-with-multi-line-comments.sql"));
+
+ assertUsersDatabaseCreated("Hoeller", "Brannen");
+ }
+
+ private void assertUsersDatabaseCreated(String... lastNames) {
+ final JdbcTemplate jdbcTemplate = new JdbcTemplate(db);
+ for (String lastName : lastNames) {
+ assertThat("Did not find user with last name [" + lastName + "].",
+ jdbcTemplate.queryForObject("select count(0) from users where last_name = ?", Integer.class, lastName),
+ equalTo(1));
+ }
+ }
+
+}
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java
similarity index 61%
rename from spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsTests.java
rename to spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java
index dff78a50b9..6df2eb1793 100644
--- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsTests.java
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java
@@ -16,44 +16,27 @@
package org.springframework.jdbc.datasource.init;
-import java.sql.Connection;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
-import org.junit.After;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.EncodedResource;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
-import org.springframework.transaction.support.TransactionSynchronizationManager;
-import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
+import static org.springframework.jdbc.datasource.init.ScriptUtils.*;
/**
- * Unit and integration tests for {@link ScriptUtils}.
+ * Unit tests for {@link ScriptUtils}.
*
* @author Thomas Risberg
* @author Sam Brannen
* @author Phillip Webb
* @author Chris Baldwin
+ * @see ScriptUtilsIntegrationTests
+ * @since 4.0.3
*/
-public class ScriptUtilsTests {
-
- private final EmbeddedDatabase db = new EmbeddedDatabaseBuilder().build();
-
-
- @After
- public void shutDown() {
- if (TransactionSynchronizationManager.isSynchronizationActive()) {
- TransactionSynchronizationManager.clear();
- TransactionSynchronizationManager.unbindResource(db);
- }
- db.shutdown();
- }
+public class ScriptUtilsUnitTests {
@Test
public void splitSqlScriptDelimitedWithSemicolon() {
@@ -66,7 +49,7 @@ public class ScriptUtilsTests {
char delim = ';';
String script = rawStatement1 + delim + rawStatement2 + delim + rawStatement3 + delim;
List