Introduce SQL script exception hierarchy

This commit continues the work began in SPR-9531 as follows.

 - ScriptException now extends DataAccessException.

 - DatabasePopulator.populate() now explicitly throws ScriptException.

 - Introduced UncategorizedScriptException.

 - DatabasePopulatorUtils.execute() now throws an
   UncategorizedScriptException instead of a
   DataAccessResourceFailureException.

Issue: SPR-11564
This commit is contained in:
Sam Brannen 2014-03-17 12:26:32 +01:00
parent f68bd5c8b2
commit fbd25467c4
7 changed files with 83 additions and 24 deletions

View File

@ -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.
@ -23,10 +23,11 @@ import java.util.List;
/**
* {@link DatabasePopulator} implementation that delegates to a list of other
* DatabasePopulator implementations, executing all scripts.
* {@code DatabasePopulator} implementations, executing all scripts.
*
* @author Dave Syer
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.1
*/
public class CompositeDatabasePopulator implements DatabasePopulator {
@ -49,9 +50,11 @@ public class CompositeDatabasePopulator implements DatabasePopulator {
this.populators.addAll(Arrays.asList(populators));
}
/**
* {@inheritDoc}
*/
@Override
public void populate(Connection connection) throws SQLException {
public void populate(Connection connection) throws SQLException, ScriptException {
for (DatabasePopulator populator : this.populators) {
populator.populate(connection);
}

View File

@ -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.
@ -23,16 +23,22 @@ import java.sql.SQLException;
* Strategy used to populate a database during initialization.
*
* @author Keith Donald
* @author Sam Brannen
* @since 3.0
* @see ResourceDatabasePopulator
* @see DatabasePopulatorUtils
*/
public interface DatabasePopulator {
/**
* Populate the database using the JDBC connection provided.
* @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 during database population
* @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
* during database population
* @throws ScriptException in all other error cases
* @see DatabasePopulatorUtils#execute
*/
void populate(Connection connection) throws SQLException;
void populate(Connection connection) throws SQLException, ScriptException;
}

View File

@ -21,7 +21,6 @@ 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;
@ -39,7 +38,7 @@ public abstract class DatabasePopulatorUtils {
* 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
* @throws DataAccessException if an error occurs, specifically a {@link ScriptException}
*/
public static void execute(DatabasePopulator populator, DataSource dataSource) throws DataAccessException {
Assert.notNull(populator, "DatabasePopulator must be provided");
@ -56,7 +55,11 @@ public abstract class DatabasePopulatorUtils {
}
}
catch (Exception ex) {
throw new DataAccessResourceFailureException("Failed to execute database script", ex);
if (ex instanceof ScriptException) {
throw (ScriptException) ex;
}
throw new UncategorizedScriptException("Failed to execute database script", ex);
}
}

View File

@ -179,8 +179,11 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
this.ignoreFailedDrops = ignoreFailedDrops;
}
/**
* {@inheritDoc}
*/
@Override
public void populate(Connection connection) throws SQLException {
public void populate(Connection connection) throws SQLException, ScriptException {
for (Resource script : this.scripts) {
ScriptUtils.executeSqlScript(connection, encodeScript(script), this.continueOnError,
this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter,

View File

@ -16,14 +16,17 @@
package org.springframework.jdbc.datasource.init;
import org.springframework.dao.DataAccessException;
/**
* Root of the hierarchy of SQL script exceptions.
* Root of the hierarchy of data access exceptions that are related to processing
* of SQL scripts.
*
* @author Sam Brannen
* @since 4.0.3
*/
@SuppressWarnings("serial")
public abstract class ScriptException extends RuntimeException {
public abstract class ScriptException extends DataAccessException {
/**
* Constructor for {@code ScriptException}.

View File

@ -0,0 +1,47 @@
/*
* 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;
/**
* Thrown when we cannot determine anything more specific than "something went
* wrong while processing an SQL script": for example, a {@link java.sql.SQLException}
* from JDBC that we cannot pinpoint more precisely.
*
* @author Sam Brannen
* @since 4.0.3
*/
@SuppressWarnings("serial")
public class UncategorizedScriptException extends ScriptException {
/**
* Construct a new {@code UncategorizedScriptException}.
* @param message detailed message
*/
public UncategorizedScriptException(String message) {
super(message);
}
/**
* Construct a new {@code UncategorizedScriptException}.
* @param message detailed message
* @param cause the root cause
*/
public UncategorizedScriptException(String message, Throwable cause) {
super(message, cause);
}
}

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");
* you may not use this file except in compliance with the License.
@ -19,7 +19,6 @@ package org.springframework.jdbc.datasource.embedded;
import org.junit.Test;
import org.springframework.core.io.ClassRelativeResourceLoader;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.init.CannotReadScriptException;
@ -27,6 +26,7 @@ import static org.junit.Assert.*;
/**
* @author Keith Donald
* @author Sam Brannen
*/
public class EmbeddedDatabaseBuilderTests {
@ -80,15 +80,9 @@ public class EmbeddedDatabaseBuilderTests {
assertDatabaseCreatedAndShutdown(db);
}
@Test
@Test(expected = CannotReadScriptException.class)
public void testBuildNoSuchScript() {
try {
new EmbeddedDatabaseBuilder().addScript("bogus.sql").build();
fail("Should have failed");
}
catch (DataAccessResourceFailureException ex) {
assertTrue(ex.getCause() instanceof CannotReadScriptException);
}
new EmbeddedDatabaseBuilder().addScript("bogus.sql").build();
}
private void assertDatabaseCreatedAndShutdown(EmbeddedDatabase db) {