diff --git a/spring-core/src/main/java/org/springframework/core/io/support/EncodedResource.java b/spring-core/src/main/java/org/springframework/core/io/support/EncodedResource.java index 04a173836c1..59643dd6b21 100644 --- a/spring-core/src/main/java/org/springframework/core/io/support/EncodedResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/support/EncodedResource.java @@ -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"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ import org.springframework.util.ObjectUtils; * with a specific encoding to be used for reading from the resource. * *
Used as argument for operations that support to read content with - * a specific encoding (usually through a {@code java.io.Reader}. + * a specific encoding (usually through a {@code java.io.Reader}). * * @author Juergen Hoeller * @since 1.2.6 diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CannotReadScriptException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CannotReadScriptException.java index 93388defff4..7ab5b198bbc 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CannotReadScriptException.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CannotReadScriptException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * 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. @@ -19,14 +19,14 @@ package org.springframework.jdbc.datasource.init; import org.springframework.core.io.support.EncodedResource; /** - * Thrown by {@link ResourceDatabasePopulator} if one of its SQL scripts cannot - * be read during population. + * Thrown by {@link ScriptUtils} if an SQL script cannot be read. * * @author Keith Donald + * @author Sam Brannen * @since 3.0 */ @SuppressWarnings("serial") -public class CannotReadScriptException extends RuntimeException { +public class CannotReadScriptException extends ScriptException { /** * Construct a new {@code CannotReadScriptException}. 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 1f046d07d26..6125ae9fd98 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-2012 the original author or authors. + * 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. @@ -20,25 +20,28 @@ import java.sql.Connection; import javax.sql.DataSource; +import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.util.Assert; /** - * Utility methods for executing a DatabasePopulator. + * Utility methods for executing a {@link DatabasePopulator}. * * @author Juergen Hoeller * @author Oliver Gierke + * @author Sam Brannen * @since 3.1 */ public abstract class DatabasePopulatorUtils { /** - * Execute the given DatabasePopulator against the given DataSource. - * @param populator the DatabasePopulator to execute - * @param dataSource the DataSource to execute against + * Execute the given {@link DatabasePopulator} against the given {@link DataSource}. + * @param populator the {@code DatabasePopulator} to execute + * @param dataSource the {@code DataSource} to execute against + * @throws DataAccessException if an error occurs */ - public static void execute(DatabasePopulator populator, DataSource dataSource) { + public static void execute(DatabasePopulator populator, DataSource dataSource) throws DataAccessException { Assert.notNull(populator, "DatabasePopulator must be provided"); Assert.notNull(dataSource, "DataSource must be provided"); try { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java index 05d7a7b84ac..c2ebb314c07 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java @@ -18,16 +18,12 @@ package org.springframework.jdbc.datasource.init; import java.sql.Connection; import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.springframework.core.io.Resource; import org.springframework.core.io.support.EncodedResource; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.UncategorizedSQLException; -import org.springframework.jdbc.datasource.init.ScriptUtils.ScriptStatementExecutor; /** * Populates a database from SQL scripts defined in external resources. @@ -55,9 +51,9 @@ public class ResourceDatabasePopulator implements DatabasePopulator { private String commentPrefix = ScriptUtils.DEFAULT_COMMENT_PREFIX; private String blockCommentStartDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER; - + private String blockCommentEndDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER; - + private boolean continueOnError = false; private boolean ignoreFailedDrops = false; @@ -65,7 +61,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator { /** * Add a script to execute to populate the database. - * @param script the path to a SQL script + * @param script the path to an SQL script */ public void addScript(Resource script) { this.scripts.add(script); @@ -81,8 +77,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator { /** * Specify the encoding for SQL scripts, if different from the platform encoding. - * Note setting this property has no effect on added scripts that are already - * {@link EncodedResource encoded resources}. + *
Note that setting this property has no effect on added scripts that are + * already {@linkplain EncodedResource encoded resources}. * @see #addScript(Resource) */ public void setSqlScriptEncoding(String sqlScriptEncoding) { @@ -90,41 +86,46 @@ public class ResourceDatabasePopulator implements DatabasePopulator { } /** - * Specify the statement separator, if a custom one. Default is ";". + * Specify the statement separator, if a custom one. + *
Default is ";". */ public void setSeparator(String separator) { this.separator = separator; } /** - * Set the line prefix that identifies comments in the SQL script. - * Default is "--". + * Set the prefix that identifies line comments within the SQL scripts. + *
Default is "--". */ public void setCommentPrefix(String commentPrefix) { this.commentPrefix = commentPrefix; } /** - * Set the block comment start delimiter in the SQL script. - * Default is "/*" + * Set the start delimiter that identifies block comments within the SQL + * scripts. + *
Default is "/*". * @since 4.0.3 + * @see #setBlockCommentEndDelimiter */ public void setBlockCommentStartDelimiter(String blockCommentStartDelimiter) { - this.blockCommentStartDelimiter = blockCommentStartDelimiter; + this.blockCommentStartDelimiter = blockCommentStartDelimiter; } - + /** - * Set the block comment end delimiter in the SQL script. - * Default is "*\/" + * Set the end delimiter that identifies block comments within the SQL + * scripts. + *
Default is "*/". * @since 4.0.3 + * @see #setBlockCommentStartDelimiter */ public void setBlockCommentEndDelimiter(String blockCommentEndDelimiter) { this.blockCommentEndDelimiter = blockCommentEndDelimiter; } - + /** * Flag to indicate that all failures in SQL should be logged but not cause a failure. - * Defaults to false. + *
Defaults to {@code false}. */ public void setContinueOnError(boolean continueOnError) { this.continueOnError = continueOnError; @@ -133,44 +134,20 @@ public class ResourceDatabasePopulator implements DatabasePopulator { /** * Flag to indicate that a failed SQL {@code DROP} statement can be ignored. *
This is useful for non-embedded databases whose SQL dialect does not support an - * {@code IF EXISTS} clause in a {@code DROP}. The default is false so that if the - * populator runs accidentally, it will fail fast when the script starts with a {@code DROP}. + * {@code IF EXISTS} clause in a {@code DROP} statement. + *
The default is {@code false} so that if the populator runs accidentally, it will
+ * fail fast if the script starts with a {@code DROP} statement.
*/
public void setIgnoreFailedDrops(boolean ignoreFailedDrops) {
this.ignoreFailedDrops = ignoreFailedDrops;
}
-
@Override
public void populate(Connection connection) throws SQLException {
- Statement statement = null;
- try {
- statement = connection.createStatement();
- final Statement stmt = statement;
- for (Resource script : this.scripts) {
- ScriptUtils.executeSqlScript(
- new ScriptStatementExecutor() {
-
- @Override
- public int executeScriptStatement(String statement) throws DataAccessException {
- try {
- stmt.execute(statement);
- return stmt.getUpdateCount();
- }
- catch (SQLException e) {
- throw new UncategorizedSQLException(getClass().getName(), statement, e);
- }
- }
- },
- applyEncodingIfNecessary(script), this.continueOnError, this.ignoreFailedDrops,
- this.commentPrefix, this.separator, this.blockCommentStartDelimiter,
- this.blockCommentEndDelimiter);
- }
- }
- finally {
- if (statement != null) {
- statement.close();
- }
+ for (Resource script : this.scripts) {
+ ScriptUtils.executeSqlScript(connection, applyEncodingIfNecessary(script), this.continueOnError,
+ this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter,
+ this.blockCommentEndDelimiter);
}
}
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java
new file mode 100644
index 00000000000..31c8a9618d2
--- /dev/null
+++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+/**
+ * Root of the hierarchy of SQL script exceptions.
+ *
+ * @author Sam Brannen
+ * @since 4.0.3
+ */
+@SuppressWarnings("serial")
+public abstract class ScriptException extends RuntimeException {
+
+ /**
+ * Constructor for {@code ScriptException}.
+ * @param message the detail message
+ */
+ public ScriptException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor for {@code ScriptException}.
+ * @param message the detail message
+ * @param cause the root cause
+ */
+ public ScriptException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java
new file mode 100644
index 00000000000..63edc6b03fe
--- /dev/null
+++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java
@@ -0,0 +1,54 @@
+/*
+ * 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.core.io.support.EncodedResource;
+
+/**
+ * Thrown by {@link ScriptUtils} if an SQL script cannot be properly parsed.
+ *
+ * @author Sam Brannen
+ * @since 4.0.3
+ */
+@SuppressWarnings("serial")
+public class ScriptParseException extends ScriptException {
+
+ /**
+ * Construct a new {@code ScriptParseException}.
+ * @param message detailed message
+ * @param resource the resource from which the SQL script was read
+ */
+ public ScriptParseException(String message, EncodedResource resource) {
+ super(buildMessage(message, resource));
+ }
+
+ /**
+ * Construct a new {@code ScriptParseException}.
+ * @param message detailed message
+ * @param resource the resource from which the SQL script was read
+ * @param cause the underlying cause of the failure
+ */
+ public ScriptParseException(String message, EncodedResource resource, Throwable cause) {
+ super(buildMessage(message, resource), cause);
+ }
+
+ private static String buildMessage(String message, EncodedResource resource) {
+ return String.format("Failed to parse SQL script from resource [%s]: %s", (resource == null ? " Within a statement, "{@code --}" 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 statement. In addition, multiple adjacent
- * whitespace characters will be collapsed into a single space.
+ * 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 delim character delimiting each statement — typically a ';' character
+ * @param delimiter character delimiting each statement — typically a ';' character
* @param statements the list that will contain the individual statements
- * @since 4.0.3
+ * @see #splitSqlScript(EncodedResource, String, String, String, String, String, List)
*/
- public static void splitSqlScript(String script, char delim, List Within a statement, the provided {@code commentPrefix} will be honored;
+ * Within the script, the provided {@code commentPrefix} will be honored:
* any text beginning with the comment prefix and extending to the end of the
- * line will be omitted from the statement. In addition, multiple adjacent
- * whitespace characters will be collapsed into a single space.
- * @param script the SQL script
- * @param delim character delimiting each statement — typically a ';' character
- * @param commentPrefix the prefix that identifies line comments in the SQL script — typically "--"
- * @param statements the List that will contain the individual statements
- * @since 4.0.3
+ * line will be omitted from the output. Similarly, the provided
+ * {@code blockCommentStartDelimiter} and {@code blockCommentEndDelimiter}
+ * delimiters will be honored: 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 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 commentPrefix the prefix that identifies SQL line comments —
+ * typically "--"; never {@code null} or empty
+ * @param blockCommentStartDelimiter the start block comment delimiter;
+ * never {@code null} or empty
+ * @param blockCommentEndDelimiter the end block comment delimiter;
+ * never {@code null} or empty
+ * @param statements the list that will contain the individual statements
*/
- public static void splitSqlScript(String script, String delim, String commentPrefix, String blockCommentOpen,
- String blockCommentClose, 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.
* @param resource the {@code EncodedResource} containing the script
* to be processed
- * @param commentPrefix the prefix that identifies comments in the SQL script — typically "--"
+ * @param commentPrefix the prefix that identifies comments in the SQL script —
+ * typically "--"
* @param separator the statement separator in the SQL script — typically ";"
* @return a {@code String} containing the script lines
- * @since 4.0.3
*/
- public static String readScript(EncodedResource resource, String commentPrefix,
- String separator) throws IOException {
+ private static String readScript(EncodedResource resource, String commentPrefix, String separator)
+ throws IOException {
LineNumberReader lnr = new LineNumberReader(resource.getReader());
try {
return readScript(lnr, commentPrefix, separator);
@@ -212,27 +238,28 @@ public abstract class ScriptUtils {
lnr.close();
}
}
-
+
/**
* Read a script from the provided {@code LineNumberReader}, using the supplied
- * comment prefix and statement separator, and build a {@code String} containing the lines.
+ * comment prefix and statement separator, and build a {@code String} containing
+ * the lines.
* 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.
* @param lineNumberReader the {@code LineNumberReader} containing the script
* to be processed
- * @param commentPrefix the prefix that identifies comments in the SQL script — typically "--"
+ * @param commentPrefix the prefix that identifies comments in the SQL script —
+ * typically "--"
* @param separator the statement separator in the SQL script — typically ";"
* @return a {@code String} containing the script lines
- * @since 4.0.3
*/
- public static String readScript(LineNumberReader lineNumberReader, String commentPrefix,
- String separator) throws IOException {
+ public static String readScript(LineNumberReader lineNumberReader, String commentPrefix, String separator)
+ throws IOException {
String currentStatement = lineNumberReader.readLine();
StringBuilder scriptBuilder = new StringBuilder();
while (currentStatement != null) {
- if (StringUtils.hasText(currentStatement) &&
- (commentPrefix != null && !currentStatement.startsWith(commentPrefix))) {
+ if (StringUtils.hasText(currentStatement)
+ && (commentPrefix != null && !currentStatement.startsWith(commentPrefix))) {
if (scriptBuilder.length() > 0) {
scriptBuilder.append('\n');
}
@@ -259,21 +286,10 @@ public abstract class ScriptUtils {
}
}
- /**
- * Does the provided SQL script contain the specified delimiter?
- * @param script the SQL script
- * @param delim character delimiting each statement - typically a ';' character
- * @since 4.0.3
- */
- public static boolean containsSqlScriptDelimiters(String script, char delim) {
- return containsSqlScriptDelimiters(script, String.valueOf(delim));
- }
-
/**
* Does the provided SQL script contain the specified delimiter?
* @param script the SQL script
* @param delim String delimiting each statement - typically a ';' character
- * @since 4.0.3
*/
public static boolean containsSqlScriptDelimiters(String script, String delim) {
boolean inLiteral = false;
@@ -291,24 +307,29 @@ public abstract class ScriptUtils {
/**
* Execute the given SQL script.
- * The script will normally be loaded by classpath. There should be one statement
- * per line. Any statement separators will be removed.
+ * 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 executor the {@code ScriptStatementExecutor} with which to perform JDBC operations
- * @param resource the resource (potentially associated with a specific encoding) to load the SQL script from
- * @param continueOnError whether or not to continue without throwing an exception in the event of an error
- * @param ignoreFailedDrops whether of not to continue in the event of specifically an error on a {@code DROP}
- * @param commentPrefix the script line comment prefix
- * if not specified
- * @param separator the script statement separator, defaults to {@code DEFAUT_STATEMENT_SEPARATOR}
- * if not specified
- * @param blockCommentStartDelim the script block comment starting delimiter
- * @param blockCommentEndDelim the script block comment ending delimiter
- * @since 4.0.3
+ * @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
+ * @param continueOnError whether or not to continue without throwing an exception
+ * in the event of an error
+ * @param ignoreFailedDrops whether or not to continue in the event of specifically
+ * an error on a {@code DROP} statement
+ * @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
+ * @param blockCommentStartDelimiter the start block comment delimiter; never
+ * {@code null} or empty
+ * @param blockCommentEndDelimiter the end block comment delimiter; never
+ * {@code null} or empty
*/
- public static void executeSqlScript(ScriptStatementExecutor executor, EncodedResource resource,
- boolean continueOnError, boolean ignoreFailedDrops, String commentPrefix, String separator,
- String blockCommentStartDelim, String blockCommentEndDelim) throws DataAccessException {
+ public static void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError,
+ boolean ignoreFailedDrops, String commentPrefix, String separator, String blockCommentStartDelimiter,
+ String blockCommentEndDelimiter) throws SQLException, ScriptException {
if (logger.isInfoEnabled()) {
logger.info("Executing SQL script from " + resource);
@@ -322,54 +343,55 @@ public abstract class ScriptUtils {
catch (IOException ex) {
throw new CannotReadScriptException(resource, ex);
}
+
if (separator == null) {
separator = DEFAULT_STATEMENT_SEPARATOR;
if (!containsSqlScriptDelimiters(script, separator)) {
separator = "\n";
}
}
- splitSqlScript(script, separator, commentPrefix, blockCommentStartDelim, blockCommentEndDelim, statements);
+
+ splitSqlScript(resource, script, separator, commentPrefix, blockCommentStartDelimiter,
+ blockCommentEndDelimiter, statements);
int lineNumber = 0;
- for (String statement : statements) {
- lineNumber++;
- try {
- int rowsAffected = executor.executeScriptStatement(statement);
- if (logger.isDebugEnabled()) {
- logger.debug(rowsAffected + " returned as updateCount for SQL: " + statement);
- }
- }
- catch (DataAccessException ex) {
- boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop");
- if (continueOnError || (dropStatement && ignoreFailedDrops)) {
+ Statement stmt = connection.createStatement();
+ try {
+ for (String statement : statements) {
+ lineNumber++;
+ try {
+ stmt.execute(statement);
+ int rowsAffected = stmt.getUpdateCount();
if (logger.isDebugEnabled()) {
- logger.debug("Failed to execute SQL script statement at line " + lineNumber +
- " of resource " + resource + ": " + statement, ex);
+ logger.debug(rowsAffected + " returned as updateCount for SQL: " + statement);
}
}
- else {
- throw new ScriptStatementFailedException(statement, lineNumber, resource, ex);
+ catch (SQLException ex) {
+ boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop");
+ if (continueOnError || (dropStatement && ignoreFailedDrops)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Failed to execute SQL script statement at line " + lineNumber
+ + " of resource " + resource + ": " + statement, ex);
+ }
+ }
+ else {
+ throw new ScriptStatementFailedException(statement, lineNumber, resource, ex);
+ }
}
}
}
+ finally {
+ try {
+ stmt.close();
+ }
+ catch (Throwable ex) {
+ logger.debug("Could not close JDBC Statement", ex);
+ }
+ }
+
long elapsedTime = System.currentTimeMillis() - startTime;
if (logger.isInfoEnabled()) {
- logger.info("Done executing SQL script from " + resource + " in " + elapsedTime + " ms.");
+ logger.info("Executed SQL script from " + resource + " in " + elapsedTime + " ms.");
}
}
- /**
- * Interface to be implemented by an object so that {@code executeScript()} is able to use
- * it to execute script statements.
- * @since 4.0.3
- */
- public interface ScriptStatementExecutor
- {
- /**
- * Execute the given SQL statement and return a count of the number of affected rows.
- * @return the number of rows affected by the statement
- * @throws DataAccessException if there is a problem during statement execution
- */
- public int executeScriptStatement(String statement) throws DataAccessException;
- }
-
}
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 68f33bcf82f..73f3629ba5d 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-2013 the original author or authors.
+ * 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.
@@ -40,9 +40,7 @@ import static org.mockito.BDDMockito.*;
*/
public class DatabasePopulatorTests {
- private final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
-
- private final EmbeddedDatabase db = builder.build();
+ private final EmbeddedDatabase db = new EmbeddedDatabaseBuilder().build();
private final ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
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/ScriptUtilsTests.java
index f7d9e9764ab..dff78a50b90 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/ScriptUtilsTests.java
@@ -16,10 +16,8 @@
package org.springframework.jdbc.datasource.init;
-import java.io.LineNumberReader;
import java.sql.Connection;
import java.sql.SQLException;
-import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
@@ -27,8 +25,6 @@ import org.junit.After;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.EncodedResource;
-import org.springframework.dao.DataAccessException;
-import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
@@ -37,20 +33,19 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
-
/**
- * JUnit test cases for ScriptUtils.
- *
+ * Unit and integration tests for {@link ScriptUtils}.
+ *
+ * @author Thomas Risberg
+ * @author Sam Brannen
+ * @author Phillip Webb
* @author Chris Baldwin
*/
public class ScriptUtilsTests {
- private final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
+ private final EmbeddedDatabase db = new EmbeddedDatabaseBuilder().build();
- private final EmbeddedDatabase db = builder.build();
- private final JdbcTemplate jdbcTemplate = new JdbcTemplate(db);
-
@After
public void shutDown() {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
@@ -95,11 +90,9 @@ public class ScriptUtilsTests {
@Test
public void readAndSplitScriptContainingComments() throws Exception {
-
EncodedResource resource = new EncodedResource(new ClassPathResource("test-data-with-comments.sql", getClass()));
- LineNumberReader lineNumberReader = new LineNumberReader(resource.getReader());
- String script = ScriptUtils.readScript(lineNumberReader);
+ String script = ScriptUtils.readScript(resource);
char delim = ';';
List Use with caution outside of a transaction!
- * The script will normally be loaded by classpath. There should be one
- * statement per line. Any semicolons will be removed. Do not use this
- * method to execute DDL if you expect rollback.
+ * The script will normally be loaded by classpath.
+ * Do not use this method to execute DDL if you expect rollback.
* @param sqlResourcePath the Spring resource path for the SQL script
* @param continueOnError whether or not to continue without throwing an
* exception in the event of an error
* @throws DataAccessException if there is an error executing a statement
- * and continueOnError was {@code false}
- * @see JdbcTestUtils#executeSqlScript(JdbcTemplate, EncodedResource, boolean)
+ * @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
* @see #setSqlScriptEncoding
*/
- @SuppressWarnings("deprecation")
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
Resource resource = this.applicationContext.getResource(sqlResourcePath);
- JdbcTestUtils.executeSqlScript(this.jdbcTemplate, new EncodedResource(resource, this.sqlScriptEncoding),
- continueOnError);
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.setContinueOnError(continueOnError);
+ databasePopulator.addScript(resource);
+ databasePopulator.setSqlScriptEncoding(this.sqlScriptEncoding);
+
+ DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
}
}
diff --git a/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.java b/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.java
index 0e1d6712b83..3d99d31c71f 100644
--- a/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.java
+++ b/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.java
@@ -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");
* you may not use this file except in compliance with the License.
@@ -21,9 +21,10 @@ import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.EncodedResource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.test.jdbc.JdbcTestUtils;
@@ -162,22 +163,24 @@ public abstract class AbstractTransactionalTestNGSpringContextTests extends Abst
/**
* Execute the given SQL script.
* Use with caution outside of a transaction!
- * The script will normally be loaded by classpath. There should be one
- * statement per line. Any semicolons will be removed. Do not use this
- * method to execute DDL if you expect rollback.
+ * The script will normally be loaded by classpath.
+ * Do not use this method to execute DDL if you expect rollback.
* @param sqlResourcePath the Spring resource path for the SQL script
* @param continueOnError whether or not to continue without throwing an
* exception in the event of an error
* @throws DataAccessException if there is an error executing a statement
- * and continueOnError was {@code false}
- * @see JdbcTestUtils#executeSqlScript(JdbcTemplate, EncodedResource, boolean)
+ * @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
* @see #setSqlScriptEncoding
*/
- @SuppressWarnings("deprecation")
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
Resource resource = this.applicationContext.getResource(sqlResourcePath);
- JdbcTestUtils.executeSqlScript(this.jdbcTemplate, new EncodedResource(resource, this.sqlScriptEncoding),
- continueOnError);
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.setContinueOnError(continueOnError);
+ databasePopulator.addScript(resource);
+ databasePopulator.setSqlScriptEncoding(this.sqlScriptEncoding);
+
+ DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
}
}
diff --git a/spring-test/src/main/java/org/springframework/test/jdbc/JdbcTestUtils.java b/spring-test/src/main/java/org/springframework/test/jdbc/JdbcTestUtils.java
index e3eab00efca..dd74f449f66 100644
--- a/spring-test/src/main/java/org/springframework/test/jdbc/JdbcTestUtils.java
+++ b/spring-test/src/main/java/org/springframework/test/jdbc/JdbcTestUtils.java
@@ -22,15 +22,16 @@ 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.ResourceLoader;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameterValue;
+import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.jdbc.datasource.init.ScriptUtils;
-import org.springframework.jdbc.datasource.init.ScriptUtils.ScriptStatementExecutor;
import org.springframework.util.StringUtils;
/**
@@ -48,6 +49,7 @@ public class JdbcTestUtils {
private static final Log logger = LogFactory.getLog(JdbcTestUtils.class);
+
/**
* Count the rows in the given table.
* @param jdbcTemplate the JdbcTemplate with which to perform JDBC operations
@@ -117,14 +119,13 @@ public class JdbcTestUtils {
* optionally the scale.
* @return the number of rows deleted from the table
*/
- public static int deleteFromTableWhere(JdbcTemplate jdbcTemplate, String tableName,
- String whereClause, Object... args) {
+ public static int deleteFromTableWhere(JdbcTemplate jdbcTemplate, String tableName, String whereClause,
+ Object... args) {
String sql = "DELETE FROM " + tableName;
if (StringUtils.hasText(whereClause)) {
sql += " WHERE " + whereClause;
}
- int rowCount = (args != null && args.length > 0 ? jdbcTemplate.update(sql, args)
- : jdbcTemplate.update(sql));
+ int rowCount = (args != null && args.length > 0 ? jdbcTemplate.update(sql, args) : jdbcTemplate.update(sql));
if (logger.isInfoEnabled()) {
logger.info("Deleted " + rowCount + " rows from table " + tableName);
}
@@ -158,9 +159,11 @@ public class JdbcTestUtils {
* @throws DataAccessException if there is an error executing a statement
* and {@code continueOnError} is {@code false}
* @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
* @see #executeSqlScript(JdbcTemplate, Resource, boolean)
- * @deprecated as of Spring 4.0.3, in favor of using
- * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript(ScriptStatementExecutor, EncodedResource, boolean, boolean, String, String, String, String)}
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript}
+ * or {@link org.springframework.jdbc.datasource.init.ResourceDatabasePopulator}.
*/
@Deprecated
public static void executeSqlScript(JdbcTemplate jdbcTemplate, ResourceLoader resourceLoader,
@@ -184,9 +187,11 @@ public class JdbcTestUtils {
* @throws DataAccessException if there is an error executing a statement
* and {@code continueOnError} is {@code false}
* @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
* @see #executeSqlScript(JdbcTemplate, EncodedResource, boolean)
- * @deprecated as of Spring 4.0.3, in favor of using
- * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript(ScriptStatementExecutor, EncodedResource, boolean, boolean, String, String, String, String)}
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript}
+ * or {@link org.springframework.jdbc.datasource.init.ResourceDatabasePopulator}.
*/
@Deprecated
public static void executeSqlScript(JdbcTemplate jdbcTemplate, Resource resource, boolean continueOnError)
@@ -207,36 +212,22 @@ public class JdbcTestUtils {
* @throws DataAccessException if there is an error executing a statement
* and {@code continueOnError} is {@code false}
* @see ResourceDatabasePopulator
- * @deprecated as of Spring 4.0.3, in favor of using
- * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript(ScriptStatementExecutor, EncodedResource, boolean, boolean, String, String, String, String)}
+ * @see DatabasePopulatorUtils
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript}
+ * or {@link org.springframework.jdbc.datasource.init.ResourceDatabasePopulator}.
*/
@Deprecated
public static void executeSqlScript(JdbcTemplate jdbcTemplate, EncodedResource resource, boolean continueOnError)
throws DataAccessException {
- ScriptUtils.executeSqlScript(new JdbcTemplateScriptStatementExecutor(jdbcTemplate), resource,
- continueOnError, continueOnError, ScriptUtils.DEFAULT_COMMENT_PREFIX,
- ScriptUtils.DEFAULT_STATEMENT_SEPARATOR, ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER,
- ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER);
- }
-
- private static class JdbcTemplateScriptStatementExecutor implements ScriptStatementExecutor {
-
- private JdbcTemplate jdbcTemplate;
-
- public JdbcTemplateScriptStatementExecutor(JdbcTemplate jdbcTemplate) {
- super();
- this.jdbcTemplate = jdbcTemplate;
- }
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.setContinueOnError(continueOnError);
+ databasePopulator.addScript(resource.getResource());
+ databasePopulator.setSqlScriptEncoding(resource.getEncoding());
- /* (non-Javadoc)
- * @see org.springframework.jdbc.support.JdbcUtils.ScriptStatementExecutor#executeScriptStatement(java.lang.String)
- */
- @Override
- public int executeScriptStatement(String statement) throws DataAccessException {
- return jdbcTemplate.update(statement);
- }
+ DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
}
-
+
/**
* Read a script from the provided {@code LineNumberReader}, using
* "{@code --}" as the comment prefix, and build a {@code String} containing
@@ -245,14 +236,14 @@ public class JdbcTestUtils {
* to be processed
* @return a {@code String} containing the script lines
* @see #readScript(LineNumberReader, String)
- * @deprecated as of Spring 4.0.3, in favor of using
- * {@link org.springframework.jdbc.datasource.init.ScriptUtils#readScript(LineNumberReader)}
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#readScript(LineNumberReader, String, String)}
*/
@Deprecated
public static String readScript(LineNumberReader lineNumberReader) throws IOException {
- return ScriptUtils.readScript(lineNumberReader);
+ return readScript(lineNumberReader, ScriptUtils.DEFAULT_COMMENT_PREFIX);
}
-
+
/**
* Read a script from the provided {@code LineNumberReader}, using the supplied
* comment prefix, and build a {@code String} containing the lines.
@@ -263,7 +254,7 @@ public class JdbcTestUtils {
* to be processed
* @param commentPrefix the prefix that identifies comments in the SQL script — typically "--"
* @return a {@code String} containing the script lines
- * @deprecated as of Spring 4.0.3, in favor of using
+ * @deprecated as of Spring 4.0.3, in favor of using
* {@link org.springframework.jdbc.datasource.init.ScriptUtils#readScript(LineNumberReader, String, String)}
*/
@Deprecated
@@ -276,14 +267,14 @@ public class JdbcTestUtils {
* @param script the SQL script
* @param delim character delimiting each statement — typically a ';' character
* @return {@code true} if the script contains the delimiter; {@code false} otherwise
- * @deprecated as of Spring 4.0.3, in favor of using
- * {@link org.springframework.jdbc.datasource.init.ScriptUtils#containsSqlScriptDelimiters(String, char)}
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#containsSqlScriptDelimiters}
*/
@Deprecated
public static boolean containsSqlScriptDelimiters(String script, char delim) {
- return ScriptUtils.containsSqlScriptDelimiters(script, delim);
+ return ScriptUtils.containsSqlScriptDelimiters(script, String.valueOf(delim));
}
-
+
/**
* Split an SQL script into separate statements delimited by the provided
* delimiter character. Each individual statement will be added to the
@@ -295,7 +286,7 @@ public class JdbcTestUtils {
* @param script the SQL script
* @param delim character delimiting each statement — typically a ';' character
* @param statements the list that will contain the individual statements
- * @deprecated as of Spring 4.0.3, in favor of using
+ * @deprecated as of Spring 4.0.3, in favor of using
* {@link org.springframework.jdbc.datasource.init.ScriptUtils#splitSqlScript(String, char, List)}
*/
@Deprecated
diff --git a/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsIntegrationTests.java
new file mode 100644
index 00000000000..5f9897e5bcf
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsIntegrationTests.java
@@ -0,0 +1,63 @@
+/*
+ * 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.test.jdbc;
+
+import java.util.Arrays;
+
+import org.junit.After;
+import org.junit.Test;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+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 static org.junit.Assert.*;
+
+/**
+ * Integration tests for {@link JdbcTestUtils}.
+ *
+ * @author Sam Brannen
+ * @since 4.0.3
+ * @see JdbcTestUtilsTests
+ */
+public class JdbcTestUtilsIntegrationTests {
+
+ private final EmbeddedDatabase db = new EmbeddedDatabaseBuilder().build();
+
+ private JdbcTemplate jdbcTemplate = new JdbcTemplate(db);
+
+
+ @After
+ public void shutdown() {
+ db.shutdown();
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void executeSqlScriptsAndcountRowsInTableWhere() throws Exception {
+
+ for (String script : Arrays.asList("schema.sql", "data.sql")) {
+ Resource resource = new ClassPathResource(script, getClass());
+ JdbcTestUtils.executeSqlScript(this.jdbcTemplate, new EncodedResource(resource), false);
+ }
+
+ assertEquals(1, JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "person", "name = 'bob'"));
+ }
+
+}
diff --git a/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java b/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java
index 748e4a72777..1c9452d0342 100644
--- a/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java
+++ b/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java
@@ -16,24 +16,22 @@
package org.springframework.test.jdbc;
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.mockito.BDDMockito.given;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.jdbc.core.JdbcTemplate;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.BDDMockito.*;
+
/**
* Unit tests for {@link JdbcTestUtils}.
*
- * @author Thomas Risberg
- * @author Sam Brannen
* @author Phillip Webb
- * @author Chris Baldwin
* @since 2.5.4
+ * @see JdbcTestUtilsIntegrationTests
*/
@RunWith(MockitoJUnitRunner.class)
public class JdbcTestUtilsTests {
@@ -41,6 +39,7 @@ public class JdbcTestUtilsTests {
@Mock
private JdbcTemplate jdbcTemplate;
+
@Test
public void deleteWithoutWhereClause() throws Exception {
given(jdbcTemplate.update("DELETE FROM person")).willReturn(10);
diff --git a/spring-test/src/test/resources/org/springframework/test/jdbc/data.sql b/spring-test/src/test/resources/org/springframework/test/jdbc/data.sql
new file mode 100644
index 00000000000..10d02a9c919
--- /dev/null
+++ b/spring-test/src/test/resources/org/springframework/test/jdbc/data.sql
@@ -0,0 +1 @@
+INSERT INTO person VALUES('bob');
\ No newline at end of file
diff --git a/spring-test/src/test/resources/org/springframework/test/jdbc/schema.sql b/spring-test/src/test/resources/org/springframework/test/jdbc/schema.sql
new file mode 100644
index 00000000000..d5bacef4fbd
--- /dev/null
+++ b/spring-test/src/test/resources/org/springframework/test/jdbc/schema.sql
@@ -0,0 +1,4 @@
+CREATE TABLE person (
+ name VARCHAR(20) NOT NULL,
+ PRIMARY KEY(name)
+);
\ No newline at end of file