Favor ScriptException over SQLException
In ScriptUtils and related classes, SQLExceptions are now caught and wrapped in ScriptExceptions wherever feasible. Affected "throws" declarations have also been revised as appropriate. Issue: SPR-11564
This commit is contained in:
parent
cf290ab42a
commit
92eb99a5ab
|
|
@ -13,10 +13,12 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jdbc.datasource.init;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
|
@ -44,7 +46,7 @@ public class CompositeDatabasePopulator implements DatabasePopulator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a populator to the list of delegates.
|
||||
* Add one or more populators to the list of delegates.
|
||||
*/
|
||||
public void addPopulators(DatabasePopulator... populators) {
|
||||
this.populators.addAll(Arrays.asList(populators));
|
||||
|
|
|
|||
|
|
@ -31,7 +31,12 @@ import java.sql.SQLException;
|
|||
public interface DatabasePopulator {
|
||||
|
||||
/**
|
||||
* Populate the database using the JDBC connection provided.
|
||||
* Populate the database using the provided JDBC connection.
|
||||
* <p>Concrete implementations <em>may</em> throw an {@link SQLException} if
|
||||
* an error is encountered but are <em>strongly encouraged</em> to throw a
|
||||
* specific {@link ScriptException} instead. For example, Spring's
|
||||
* {@link ResourceDatabasePopulator} and {@link DatabasePopulatorUtils} wrap
|
||||
* all {@code SQLExceptions} in {@code ScriptExceptions}.
|
||||
* @param connection the JDBC connection to use to populate the db; already
|
||||
* configured and ready to use
|
||||
* @throws SQLException if an unrecoverable data access exception occurs
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.jdbc.datasource.init;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
|
@ -183,7 +182,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void populate(Connection connection) throws SQLException, ScriptException {
|
||||
public void populate(Connection connection) throws ScriptException {
|
||||
for (Resource script : this.scripts) {
|
||||
ScriptUtils.executeSqlScript(connection, encodeScript(script), this.continueOnError,
|
||||
this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter,
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ public abstract class ScriptUtils {
|
|||
* @param script the SQL script
|
||||
* @param separator character separating each statement — typically a ';'
|
||||
* @param statements the list that will contain the individual statements
|
||||
* @throws ScriptException if an error occurred while splitting the SQL script
|
||||
* @see #splitSqlScript(String, String, List)
|
||||
* @see #splitSqlScript(EncodedResource, String, String, String, String, String, List)
|
||||
*/
|
||||
|
|
@ -121,6 +122,7 @@ public abstract class ScriptUtils {
|
|||
* @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
|
||||
* @throws ScriptException if an error occurred while splitting the SQL script
|
||||
* @see #splitSqlScript(String, char, List)
|
||||
* @see #splitSqlScript(EncodedResource, String, String, String, String, String, List)
|
||||
*/
|
||||
|
|
@ -151,6 +153,7 @@ public abstract class ScriptUtils {
|
|||
* @param blockCommentEndDelimiter the <em>end</em> block comment delimiter;
|
||||
* never {@code null} or empty
|
||||
* @param statements the list that will contain the individual statements
|
||||
* @throws ScriptException if an error occurred while splitting the SQL script
|
||||
*/
|
||||
public static void splitSqlScript(EncodedResource resource, String script, String separator, String commentPrefix,
|
||||
String blockCommentStartDelimiter, String blockCommentEndDelimiter, List<String> statements)
|
||||
|
|
@ -257,6 +260,7 @@ public abstract class ScriptUtils {
|
|||
* typically "--"
|
||||
* @param separator the statement separator in the SQL script — typically ";"
|
||||
* @return a {@code String} containing the script lines
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
private static String readScript(EncodedResource resource, String commentPrefix, String separator)
|
||||
throws IOException {
|
||||
|
|
@ -282,6 +286,7 @@ public abstract class ScriptUtils {
|
|||
* typically "--"
|
||||
* @param separator the statement separator in the SQL script — typically ";"
|
||||
* @return a {@code String} containing the script lines
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static String readScript(LineNumberReader lineNumberReader, String commentPrefix, String separator)
|
||||
throws IOException {
|
||||
|
|
@ -344,13 +349,14 @@ public abstract class ScriptUtils {
|
|||
* configured and ready to use
|
||||
* @param resource the resource to load the SQL script from; encoded with the
|
||||
* current platform's default encoding
|
||||
* @throws ScriptException if an error occurred while executing the SQL script
|
||||
* @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 {
|
||||
public static void executeSqlScript(Connection connection, Resource resource) throws ScriptException {
|
||||
executeSqlScript(connection, new EncodedResource(resource));
|
||||
}
|
||||
|
||||
|
|
@ -364,14 +370,14 @@ public abstract class ScriptUtils {
|
|||
* configured and ready to use
|
||||
* @param resource the resource (potentially associated with a specific encoding)
|
||||
* to load the SQL script from
|
||||
* @throws ScriptException if an error occurred while executing the SQL script
|
||||
* @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 {
|
||||
public static void executeSqlScript(Connection connection, EncodedResource resource) throws ScriptException {
|
||||
executeSqlScript(connection, resource, false, false, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR,
|
||||
DEFAULT_BLOCK_COMMENT_START_DELIMITER, DEFAULT_BLOCK_COMMENT_END_DELIMITER);
|
||||
}
|
||||
|
|
@ -398,71 +404,83 @@ public abstract class ScriptUtils {
|
|||
* {@code null} or empty
|
||||
* @param blockCommentEndDelimiter the <em>end</em> block comment delimiter; never
|
||||
* {@code null} or empty
|
||||
* @throws ScriptException if an error occurred while executing the SQL script
|
||||
*/
|
||||
public static void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError,
|
||||
boolean ignoreFailedDrops, String commentPrefix, String separator, String blockCommentStartDelimiter,
|
||||
String blockCommentEndDelimiter) throws SQLException, ScriptException {
|
||||
String blockCommentEndDelimiter) throws ScriptException {
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Executing SQL script from " + resource);
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
List<String> statements = new LinkedList<String>();
|
||||
String script;
|
||||
try {
|
||||
script = readScript(resource, commentPrefix, separator);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new CannotReadScriptException(resource, ex);
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Executing SQL script from " + resource);
|
||||
}
|
||||
|
||||
if (separator == null) {
|
||||
separator = DEFAULT_STATEMENT_SEPARATOR;
|
||||
}
|
||||
if (!containsSqlScriptDelimiters(script, separator)) {
|
||||
separator = FALLBACK_STATEMENT_SEPARATOR;
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
List<String> statements = new LinkedList<String>();
|
||||
String script;
|
||||
try {
|
||||
script = readScript(resource, commentPrefix, separator);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new CannotReadScriptException(resource, ex);
|
||||
}
|
||||
|
||||
splitSqlScript(resource, script, separator, commentPrefix, blockCommentStartDelimiter,
|
||||
blockCommentEndDelimiter, statements);
|
||||
int lineNumber = 0;
|
||||
Statement stmt = connection.createStatement();
|
||||
try {
|
||||
for (String statement : statements) {
|
||||
lineNumber++;
|
||||
try {
|
||||
stmt.execute(statement);
|
||||
int rowsAffected = stmt.getUpdateCount();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(rowsAffected + " returned as updateCount for SQL: " + statement);
|
||||
}
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop");
|
||||
if (continueOnError || (dropStatement && ignoreFailedDrops)) {
|
||||
if (separator == null) {
|
||||
separator = DEFAULT_STATEMENT_SEPARATOR;
|
||||
}
|
||||
if (!containsSqlScriptDelimiters(script, separator)) {
|
||||
separator = FALLBACK_STATEMENT_SEPARATOR;
|
||||
}
|
||||
|
||||
splitSqlScript(resource, script, separator, commentPrefix, blockCommentStartDelimiter,
|
||||
blockCommentEndDelimiter, statements);
|
||||
int lineNumber = 0;
|
||||
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();
|
||||
finally {
|
||||
try {
|
||||
stmt.close();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Could not close JDBC Statement", ex);
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Could not close JDBC Statement", ex);
|
||||
}
|
||||
}
|
||||
|
||||
long elapsedTime = System.currentTimeMillis() - startTime;
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Executed SQL script from " + resource + " in " + elapsedTime + " ms.");
|
||||
long elapsedTime = System.currentTimeMillis() - startTime;
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Executed SQL script from " + resource + " in " + elapsedTime + " ms.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex instanceof ScriptException) {
|
||||
throw (ScriptException) ex;
|
||||
}
|
||||
|
||||
throw new UncategorizedScriptException(
|
||||
"Failed to execute database script from resource [" + resource + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue