revised embedded database support
This commit is contained in:
parent
3ac3a72e91
commit
e9823b57b4
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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.core.io;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ResourceLoader} implementation that interprets plain resource paths
|
||||||
|
* as relative to a given <code>java.lang.Class</code>.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
* @see java.lang.Class#getResource(String)
|
||||||
|
* @see ClassPathResource#ClassPathResource(String, Class)
|
||||||
|
*/
|
||||||
|
public class ClassRelativeResourceLoader extends DefaultResourceLoader {
|
||||||
|
|
||||||
|
private final Class clazz;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ClassRelativeResourceLoader for the given class.
|
||||||
|
* @param clazz the class to load resources through
|
||||||
|
*/
|
||||||
|
public ClassRelativeResourceLoader(Class clazz) {
|
||||||
|
Assert.notNull(clazz, "Class must not be null");
|
||||||
|
this.clazz = clazz;
|
||||||
|
setClassLoader(clazz.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Resource getResourceByPath(String path) {
|
||||||
|
return new ClassRelativeContextResource(path, this.clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassPathResource that explicitly expresses a context-relative path
|
||||||
|
* through implementing the ContextResource interface.
|
||||||
|
*/
|
||||||
|
private static class ClassRelativeContextResource extends ClassPathResource implements ContextResource {
|
||||||
|
|
||||||
|
private final Class clazz;
|
||||||
|
|
||||||
|
public ClassRelativeContextResource(String path, Class clazz) {
|
||||||
|
super(path, clazz);
|
||||||
|
this.clazz = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPathWithinContext() {
|
||||||
|
return getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource createRelative(String relativePath) {
|
||||||
|
String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
|
||||||
|
return new ClassRelativeContextResource(pathToUse, this.clazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 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.
|
||||||
|
|
@ -107,8 +107,8 @@ public class SimpleDriverDataSource extends AbstractDriverBasedDataSource {
|
||||||
* within the SimpleDriverDataSource.
|
* within the SimpleDriverDataSource.
|
||||||
* @see #setDriver
|
* @see #setDriver
|
||||||
*/
|
*/
|
||||||
public void setDriverClass(Class driverClass) {
|
public void setDriverClass(Class<? extends Driver> driverClass) {
|
||||||
this.driver = (Driver) BeanUtils.instantiateClass(driverClass);
|
this.driver = BeanUtils.instantiateClass(driverClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -13,38 +13,39 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for {@link EmbeddedDatabaseConfigurer} implementations providing common shutdown behaviour.
|
* Base class for {@link EmbeddedDatabaseConfigurer} implementations providing common shutdown behavior.
|
||||||
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
abstract class AbstractEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer {
|
abstract class AbstractEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer {
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(AbstractEmbeddedDatabaseConfigurer.class);
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
public void shutdown(DataSource dataSource, String databaseName) {
|
public void shutdown(DataSource dataSource, String databaseName) {
|
||||||
Connection connection = JdbcUtils.getConnection(dataSource);
|
|
||||||
Statement stmt = null;
|
|
||||||
try {
|
try {
|
||||||
stmt = connection.createStatement();
|
Connection connection = dataSource.getConnection();
|
||||||
|
Statement stmt = connection.createStatement();
|
||||||
stmt.execute("SHUTDOWN");
|
stmt.execute("SHUTDOWN");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException ex) {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
logger.warn("Could not shutdown embedded database", e);
|
logger.warn("Could not shutdown embedded database", ex);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
JdbcUtils.closeStatement(stmt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import org.springframework.core.io.support.EncodedResource;
|
import org.springframework.core.io.support.EncodedResource;
|
||||||
|
|
@ -20,19 +21,19 @@ import org.springframework.core.io.support.EncodedResource;
|
||||||
/**
|
/**
|
||||||
* Thrown by {@link ResourceDatabasePopulator} if one of its SQL scripts could
|
* Thrown by {@link ResourceDatabasePopulator} if one of its SQL scripts could
|
||||||
* not be read during population.
|
* not be read during population.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class CannotReadScriptException extends RuntimeException {
|
public class CannotReadScriptException extends RuntimeException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new cannot read script exception.
|
* Constructor a new CannotReadScriptException.
|
||||||
*
|
|
||||||
* @param resource the resource that could not be read from
|
* @param resource the resource that could not be read from
|
||||||
* @param cause the underlying cause of the resource access failure
|
* @param cause the underlying cause of the resource access failure
|
||||||
*/
|
*/
|
||||||
public CannotReadScriptException(EncodedResource resource, Throwable cause) {
|
public CannotReadScriptException(EncodedResource resource, Throwable cause) {
|
||||||
super("Cannot read SQL script from " + resource, cause);
|
super("Cannot read SQL script from " + resource, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,38 +13,43 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
|
import java.sql.Driver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DataSourceFactory helper that allows essential JDBC connection properties to be configured consistently,
|
* DataSourceFactory helper that allows essential JDBC connection properties to be configured consistently,
|
||||||
* independent of the actual DataSource implementation.
|
* independent of the actual DataSource implementation.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see DataSourceFactory
|
* @see DataSourceFactory
|
||||||
*/
|
*/
|
||||||
public interface ConnectionProperties {
|
public interface ConnectionProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the JDBC driver to use to connect to the database.
|
* Set the JDBC driver to use to connect to the database.
|
||||||
* @param driverClass the jdbc driver class
|
* @param driverClass the jdbc driver class
|
||||||
*/
|
*/
|
||||||
void setDriverClass(Class<?> driverClass);
|
void setDriverClass(Class driverClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the JDBC connection URL of the database.
|
* Sets the JDBC connection URL of the database.
|
||||||
* @param url the connection url
|
* @param url the connection url
|
||||||
*/
|
*/
|
||||||
void setUrl(String url);
|
void setUrl(String url);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the username to use to connect to the database.
|
* Sets the username to use to connect to the database.
|
||||||
* @param username the username
|
* @param username the username
|
||||||
*/
|
*/
|
||||||
void setUsername(String username);
|
void setUsername(String username);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the password to use to connect to the database.
|
* Sets the password to use to connect to the database.
|
||||||
* @param password the password
|
* @param password the password
|
||||||
*/
|
*/
|
||||||
void setPassword(String password);
|
void setPassword(String password);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
@ -20,21 +21,25 @@ import javax.sql.DataSource;
|
||||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates the creation of a particular DataSource implementation, such as a {@link SimpleDriverDataSource} or connection pool such as Apache DBCP or c3p0.
|
* Encapsulates the creation of a particular DataSource implementation, such as a
|
||||||
* Call {@link #getConnectionProperties()} to configure normalized DataSource properties before calling {@link #getDataSource()} to actually get the configured DataSource instance.
|
* {@link SimpleDriverDataSource} or connection pool such as Apache DBCP or C3P0.
|
||||||
|
*
|
||||||
|
* <p>Call {@link #getConnectionProperties()} to configure normalized DataSource properties
|
||||||
|
* before calling {@link #getDataSource()} to actually get the configured DataSource instance.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface DataSourceFactory {
|
public interface DataSourceFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows properties of the DataSource to be configured.
|
* Allows properties of the DataSource to be configured.
|
||||||
*/
|
*/
|
||||||
ConnectionProperties getConnectionProperties();
|
ConnectionProperties getConnectionProperties();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the DataSource with the connection properties applied.
|
* Returns the DataSource with the connection properties applied.
|
||||||
*/
|
*/
|
||||||
DataSource getDataSource();
|
DataSource getDataSource();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
|
@ -20,6 +21,7 @@ import java.sql.SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strategy used to populate an embedded database during initialization.
|
* Strategy used to populate an embedded database during initialization.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see ResourceDatabasePopulator
|
* @see ResourceDatabasePopulator
|
||||||
|
|
@ -32,4 +34,5 @@ public interface DatabasePopulator {
|
||||||
* @throws SQLException if an unrecoverable data access exception occurs during database population
|
* @throws SQLException if an unrecoverable data access exception occurs during database population
|
||||||
*/
|
*/
|
||||||
void populate(Connection connection) throws SQLException;
|
void populate(Connection connection) throws SQLException;
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,26 +13,26 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Properties;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.derby.impl.io.VFMemoryStorageFactory;
|
import org.apache.derby.impl.io.VFMemoryStorageFactory;
|
||||||
import org.apache.derby.jdbc.EmbeddedDriver;
|
import org.apache.derby.jdbc.EmbeddedDriver;
|
||||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EmbeddedDatabaseConfigurer} for the Apache Derby database.
|
* {@link EmbeddedDatabaseConfigurer} for the Apache Derby database.
|
||||||
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer {
|
final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer {
|
||||||
|
|
@ -46,9 +46,6 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure
|
||||||
|
|
||||||
private static DerbyEmbeddedDatabaseConfigurer INSTANCE;
|
private static DerbyEmbeddedDatabaseConfigurer INSTANCE;
|
||||||
|
|
||||||
private DerbyEmbeddedDatabaseConfigurer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the singleton {@link DerbyEmbeddedDatabaseConfigurer} instance.
|
* Get the singleton {@link DerbyEmbeddedDatabaseConfigurer} instance.
|
||||||
* @return the configurer
|
* @return the configurer
|
||||||
|
|
@ -59,50 +56,48 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure
|
||||||
// disable log file
|
// disable log file
|
||||||
System.setProperty("derby.stream.error.method",
|
System.setProperty("derby.stream.error.method",
|
||||||
DerbyEmbeddedDatabaseConfigurer.class.getName() + ".getNoopOutputStream");
|
DerbyEmbeddedDatabaseConfigurer.class.getName() + ".getNoopOutputStream");
|
||||||
ClassUtils.forName("org.apache.derby.jdbc.EmbeddedDriver", DerbyEmbeddedDatabaseConfigurer.class
|
|
||||||
.getClassLoader());
|
|
||||||
INSTANCE = new DerbyEmbeddedDatabaseConfigurer();
|
INSTANCE = new DerbyEmbeddedDatabaseConfigurer();
|
||||||
}
|
}
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DerbyEmbeddedDatabaseConfigurer() {
|
||||||
|
}
|
||||||
|
|
||||||
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
|
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
|
||||||
properties.setDriverClass(org.apache.derby.jdbc.EmbeddedDriver.class);
|
properties.setDriverClass(EmbeddedDriver.class);
|
||||||
properties.setUrl(String.format(URL_TEMPLATE, databaseName, "create=true"));
|
properties.setUrl(String.format(URL_TEMPLATE, databaseName, "create=true"));
|
||||||
properties.setUsername("sa");
|
properties.setUsername("sa");
|
||||||
properties.setPassword("");
|
properties.setPassword("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown(DataSource dataSource, String databaseName) {
|
public void shutdown(DataSource dataSource, String databaseName) {
|
||||||
Connection connection = null;
|
|
||||||
try {
|
try {
|
||||||
SimpleDriverDataSource shutdownDataSource = new SimpleDriverDataSource();
|
new EmbeddedDriver().connect(
|
||||||
shutdownDataSource.setDriverClass(EmbeddedDriver.class);
|
String.format(URL_TEMPLATE, databaseName, "shutdown=true"), new Properties());
|
||||||
shutdownDataSource.setUrl(String.format(URL_TEMPLATE, databaseName, "shutdown=true"));
|
}
|
||||||
connection = shutdownDataSource.getConnection();
|
catch (SQLException ex) {
|
||||||
} catch (SQLException e) {
|
if (SHUTDOWN_CODE.equals(ex.getSQLState())) {
|
||||||
if (SHUTDOWN_CODE.equals(e.getSQLState())) {
|
|
||||||
purgeDatabase(databaseName);
|
purgeDatabase(databaseName);
|
||||||
} else {
|
|
||||||
logger.warn("Could not shutdown in-memory Derby database", e);
|
|
||||||
}
|
}
|
||||||
} finally {
|
else {
|
||||||
JdbcUtils.closeConnection(connection);
|
logger.warn("Could not shutdown in-memory Derby database", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Purges the in-memory database, to prevent it from hanging around after
|
* Purge the in-memory database, to prevent it from hanging around after
|
||||||
* being shut down
|
* being shut down.
|
||||||
* @param databaseName
|
|
||||||
*/
|
*/
|
||||||
private void purgeDatabase(String databaseName) {
|
private void purgeDatabase(String databaseName) {
|
||||||
// TODO: update this code once Derby adds a proper way to remove an in-memory db
|
// TODO: update this code once Derby adds a proper way to remove an in-memory db
|
||||||
// (see http://wiki.apache.org/db-derby/InMemoryBackEndPrimer for details)
|
// (see http://wiki.apache.org/db-derby/InMemoryBackEndPrimer for details)
|
||||||
try {
|
try {
|
||||||
VFMemoryStorageFactory.purgeDatabase(new File(databaseName).getCanonicalPath());
|
VFMemoryStorageFactory.purgeDatabase(new File(databaseName).getCanonicalPath());
|
||||||
} catch (IOException ioe) {
|
}
|
||||||
logger.warn("Could not purge in-memory Derby database", ioe);
|
catch (IOException ex) {
|
||||||
|
logger.warn("Could not purge in-memory Derby database", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,9 +109,9 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure
|
||||||
static OutputStream getNoopOutputStream() {
|
static OutputStream getNoopOutputStream() {
|
||||||
return new OutputStream() {
|
return new OutputStream() {
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
// ignore the input
|
// ignore the output
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
@ -21,13 +22,15 @@ import javax.sql.DataSource;
|
||||||
* A handle to an EmbeddedDatabase instance.
|
* A handle to an EmbeddedDatabase instance.
|
||||||
* Is a {@link DataSource}.
|
* Is a {@link DataSource}.
|
||||||
* Adds a shutdown operation so the embedded database instance can be shutdown.
|
* Adds a shutdown operation so the embedded database instance can be shutdown.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface EmbeddedDatabase extends DataSource {
|
public interface EmbeddedDatabase extends DataSource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shutdown this embedded database.
|
* Shutdown this embedded database.
|
||||||
*/
|
*/
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,39 +13,55 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassRelativeResourceLoader;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A builder that provides a fluent API for constructing an embedded database.
|
* A builder that provides a fluent API for constructing an embedded database.
|
||||||
* Usage example:
|
*
|
||||||
|
* <p>Usage example:
|
||||||
* <pre>
|
* <pre>
|
||||||
* EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
* EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||||
* EmbeddedDatabase db = builder.script("schema.sql").script("test-data.sql").build();
|
* EmbeddedDatabase db = builder.script("schema.sql").script("test-data.sql").build();
|
||||||
* db.shutdown();
|
* db.shutdown();
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class EmbeddedDatabaseBuilder {
|
public class EmbeddedDatabaseBuilder {
|
||||||
|
|
||||||
private EmbeddedDatabaseFactory databaseFactory;
|
private final EmbeddedDatabaseFactory databaseFactory;
|
||||||
|
|
||||||
private ResourceDatabasePopulator databasePopulator;
|
private final ResourceDatabasePopulator databasePopulator;
|
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
|
||||||
private ResourceLoader resourceLoader;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new embedded database builder.
|
* Create a new embedded database builder.
|
||||||
*/
|
*/
|
||||||
public EmbeddedDatabaseBuilder() {
|
public EmbeddedDatabaseBuilder() {
|
||||||
init(new DefaultResourceLoader());
|
this(new DefaultResourceLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new embedded database builder withfor the given ResourceLoader.
|
||||||
|
* @param resourceLoader the ResourceLoader to delegate to
|
||||||
|
*/
|
||||||
|
public EmbeddedDatabaseBuilder(ResourceLoader resourceLoader) {
|
||||||
|
this.databaseFactory = new EmbeddedDatabaseFactory();
|
||||||
|
this.databasePopulator = new ResourceDatabasePopulator();
|
||||||
|
this.databaseFactory.setDatabasePopulator(this.databasePopulator);
|
||||||
|
this.resourceLoader = resourceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the name of the embedded database
|
* Sets the name of the embedded database
|
||||||
* Defaults to 'testdb' if not called.
|
* Defaults to 'testdb' if not called.
|
||||||
|
|
@ -53,7 +69,7 @@ public class EmbeddedDatabaseBuilder {
|
||||||
* @return this, for fluent call chaining
|
* @return this, for fluent call chaining
|
||||||
*/
|
*/
|
||||||
public EmbeddedDatabaseBuilder name(String databaseName) {
|
public EmbeddedDatabaseBuilder name(String databaseName) {
|
||||||
databaseFactory.setDatabaseName(databaseName);
|
this.databaseFactory.setDatabaseName(databaseName);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +80,7 @@ public class EmbeddedDatabaseBuilder {
|
||||||
* @return this, for fluent call chaining
|
* @return this, for fluent call chaining
|
||||||
*/
|
*/
|
||||||
public EmbeddedDatabaseBuilder type(EmbeddedDatabaseType databaseType) {
|
public EmbeddedDatabaseBuilder type(EmbeddedDatabaseType databaseType) {
|
||||||
databaseFactory.setDatabaseType(databaseType);
|
this.databaseFactory.setDatabaseType(databaseType);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,7 +90,7 @@ public class EmbeddedDatabaseBuilder {
|
||||||
* @return this, for fluent call chaining
|
* @return this, for fluent call chaining
|
||||||
*/
|
*/
|
||||||
public EmbeddedDatabaseBuilder script(String sqlResource) {
|
public EmbeddedDatabaseBuilder script(String sqlResource) {
|
||||||
databasePopulator.addScript(resourceLoader.getResource(sqlResource));
|
this.databasePopulator.addScript(resourceLoader.getResource(sqlResource));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,45 +99,28 @@ public class EmbeddedDatabaseBuilder {
|
||||||
* @return the embedded database
|
* @return the embedded database
|
||||||
*/
|
*/
|
||||||
public EmbeddedDatabase build() {
|
public EmbeddedDatabase build() {
|
||||||
return databaseFactory.getDatabase();
|
return this.databaseFactory.getDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method that creates a EmbeddedDatabaseBuilder that loads SQL resources relative to the provided class.
|
|
||||||
* @param clazz the class to load relative to
|
|
||||||
* @return the embedded database builder
|
|
||||||
*/
|
|
||||||
public static EmbeddedDatabaseBuilder relativeTo(final Class<?> clazz) {
|
|
||||||
ResourceLoader loader = new ResourceLoader() {
|
|
||||||
public ClassLoader getClassLoader() {
|
|
||||||
return getClass().getClassLoader();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Resource getResource(String location) {
|
|
||||||
return new ClassPathResource(location, clazz);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return new EmbeddedDatabaseBuilder(loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method that builds a default EmbeddedDatabase instance.
|
* Factory method that builds a default EmbeddedDatabase instance.
|
||||||
* The default instance is HSQL with a schema created from classpath:schema.sql and test-data loaded from classpath:test-data.sql.
|
* The default instance is HSQL with a schema created from "classpath:schema.sql"
|
||||||
|
* and test-data loaded from "classpath:test-data.sql".
|
||||||
* @return an embedded database
|
* @return an embedded database
|
||||||
*/
|
*/
|
||||||
public static EmbeddedDatabase buildDefault() {
|
public static EmbeddedDatabase buildDefault() {
|
||||||
return new EmbeddedDatabaseBuilder().script("schema.sql").script("test-data.sql").build();
|
return new EmbeddedDatabaseBuilder().script("schema.sql").script("test-data.sql").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmbeddedDatabaseBuilder(ResourceLoader loader) {
|
/**
|
||||||
init(loader);
|
* Factory method that creates a EmbeddedDatabaseBuilder that loads SQL resources
|
||||||
}
|
* relative to the provided class.
|
||||||
|
* @param clazz the class to load relative to
|
||||||
private void init(ResourceLoader loader) {
|
* @return the embedded database builder
|
||||||
databaseFactory = new EmbeddedDatabaseFactory();
|
*/
|
||||||
databasePopulator = new ResourceDatabasePopulator();
|
public static EmbeddedDatabaseBuilder relativeTo(Class clazz) {
|
||||||
databaseFactory.setDatabasePopulator(databasePopulator);
|
return new EmbeddedDatabaseBuilder(new ClassRelativeResourceLoader(clazz));
|
||||||
resourceLoader = loader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
@ -20,6 +21,7 @@ import javax.sql.DataSource;
|
||||||
/**
|
/**
|
||||||
* Encapsulates the configuration required to create, connect to, and shutdown a specific type of embedded database such as HSQL or H2.
|
* Encapsulates the configuration required to create, connect to, and shutdown a specific type of embedded database such as HSQL or H2.
|
||||||
* Create a implementation for each database type you wish to support; for example HSQL, H2, or some other type.
|
* Create a implementation for each database type you wish to support; for example HSQL, H2, or some other type.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,15 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps well-known {@link EmbeddedDatabaseType embedded database types} to {@link EmbeddedDatabaseConfigurer}
|
* Maps well-known {@link EmbeddedDatabaseType embedded database types} to
|
||||||
* strategies.
|
* {@link EmbeddedDatabaseConfigurer} strategies.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
@ -27,25 +29,26 @@ import org.springframework.util.Assert;
|
||||||
final class EmbeddedDatabaseConfigurerFactory {
|
final class EmbeddedDatabaseConfigurerFactory {
|
||||||
|
|
||||||
public static EmbeddedDatabaseConfigurer getConfigurer(EmbeddedDatabaseType type) throws IllegalStateException {
|
public static EmbeddedDatabaseConfigurer getConfigurer(EmbeddedDatabaseType type) throws IllegalStateException {
|
||||||
Assert.notNull(type, "The EmbeddedDatabaseType is required");
|
Assert.notNull(type, "EmbeddedDatabaseType is required");
|
||||||
try {
|
try {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case HSQL:
|
case HSQL:
|
||||||
return HsqlEmbeddedDatabaseConfigurer.getInstance();
|
return HsqlEmbeddedDatabaseConfigurer.getInstance();
|
||||||
case H2:
|
case H2:
|
||||||
return H2EmbeddedDatabaseConfigurer.getInstance();
|
return H2EmbeddedDatabaseConfigurer.getInstance();
|
||||||
case DERBY:
|
case DERBY:
|
||||||
return DerbyEmbeddedDatabaseConfigurer.getInstance();
|
return DerbyEmbeddedDatabaseConfigurer.getInstance();
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Other embedded database types not yet supported");
|
throw new UnsupportedOperationException("Other embedded database types not yet supported");
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException e) {
|
}
|
||||||
throw new IllegalStateException("Drivers for test database type [" + type
|
catch (ClassNotFoundException ex) {
|
||||||
+ "] are not available in the classpath", e);
|
throw new IllegalStateException("Driver for test database type [" + type +
|
||||||
|
"] is not available in the classpath", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmbeddedDatabaseConfigurerFactory() {
|
private EmbeddedDatabaseConfigurerFactory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,39 +13,43 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.dao.DataAccessResourceFailureException;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link EmbeddedDatabase} instance. Callers are guaranteed that the returned database has been fully
|
* Creates a {@link EmbeddedDatabase} instance. Callers are guaranteed that the returned database has been fully
|
||||||
* initialized and populated.
|
* initialized and populated.
|
||||||
* <p>
|
*
|
||||||
* Can be configured:<br>
|
* <p>Can be configured:<br>
|
||||||
* Call {@link #setDatabaseName(String)} to change the name of the database.<br>
|
* Call {@link #setDatabaseName(String)} to change the name of the database.<br>
|
||||||
* Call {@link #setDatabaseType(EmbeddedDatabaseType)} to set the database type if you wish to use one of the supported types.<br>
|
* Call {@link #setDatabaseType(EmbeddedDatabaseType)} to set the database type if you wish to use one of the supported types.<br>
|
||||||
* Call {@link #setDatabaseConfigurer(EmbeddedDatabaseConfigurer)} to configure support for your own embedded database type.<br>
|
* Call {@link #setDatabaseConfigurer(EmbeddedDatabaseConfigurer)} to configure support for your own embedded database type.<br>
|
||||||
* Call {@link #setDatabasePopulator(DatabasePopulator)} to change the algorithm used to populate the database.<br>
|
* Call {@link #setDatabasePopulator(DatabasePopulator)} to change the algorithm used to populate the database.<br>
|
||||||
* Call {@link #setDataSourceFactory(DataSourceFactory)} to change the type of DataSource used to connect to the database.<br>
|
* Call {@link #setDataSourceFactory(DataSourceFactory)} to change the type of DataSource used to connect to the database.<br>
|
||||||
* Call {@link #getDatabase()} to get the {@link EmbeddedDatabase} instance.<br>
|
* Call {@link #getDatabase()} to get the {@link EmbeddedDatabase} instance.<br>
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class EmbeddedDatabaseFactory {
|
public class EmbeddedDatabaseFactory {
|
||||||
|
|
||||||
private static Log logger = LogFactory.getLog(EmbeddedDatabaseFactory.class);
|
private static Log logger = LogFactory.getLog(EmbeddedDatabaseFactory.class);
|
||||||
|
|
||||||
private String databaseName;
|
private String databaseName = "testdb";
|
||||||
|
|
||||||
private DataSourceFactory dataSourceFactory;
|
private DataSourceFactory dataSourceFactory = new SimpleDriverDataSourceFactory();
|
||||||
|
|
||||||
private EmbeddedDatabaseConfigurer databaseConfigurer;
|
private EmbeddedDatabaseConfigurer databaseConfigurer;
|
||||||
|
|
||||||
|
|
@ -53,101 +57,114 @@ public class EmbeddedDatabaseFactory {
|
||||||
|
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a default {@link EmbeddedDatabaseFactory}.
|
* Set the name of the database. Defaults to "testdb".
|
||||||
* Calling {@link #getDatabase()} will create a embedded HSQL database of name 'testdb'.
|
* @param databaseName name of the test database
|
||||||
*/
|
*/
|
||||||
public EmbeddedDatabaseFactory() {
|
public void setDatabaseName(String databaseName) {
|
||||||
setDatabaseName("testdb");
|
Assert.notNull(databaseName, "Database name is required");
|
||||||
setDatabaseType(EmbeddedDatabaseType.HSQL);
|
this.databaseName = databaseName;
|
||||||
setDataSourceFactory(new SimpleDriverDataSourceFactory());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the name of the database. Defaults to 'testdb'.
|
* Set the type of embedded database to use. Call this when you wish to configure
|
||||||
* @param name of the test database
|
* one of the pre-supported types. Defaults to HSQL.
|
||||||
*/
|
|
||||||
public void setDatabaseName(String name) {
|
|
||||||
Assert.notNull(name, "The testDatabaseName is required");
|
|
||||||
databaseName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the type of embedded database to use. Call this when you wish to configure one of the pre-supported types.
|
|
||||||
* Defaults to HSQL.
|
|
||||||
* @param type the test database type
|
* @param type the test database type
|
||||||
*/
|
*/
|
||||||
public void setDatabaseType(EmbeddedDatabaseType type) {
|
public void setDatabaseType(EmbeddedDatabaseType type) {
|
||||||
setDatabaseConfigurer(EmbeddedDatabaseConfigurerFactory.getConfigurer(type));
|
this.databaseConfigurer = EmbeddedDatabaseConfigurerFactory.getConfigurer(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the strategy that will be used to configure the embedded database instance.
|
* Set the strategy that will be used to configure the embedded database instance.
|
||||||
* Call this when you wish to use an embedded database type not already supported.
|
* Call this when you wish to use an embedded database type not already supported.
|
||||||
* @param configurer the embedded database configurer
|
* @param configurer the embedded database configurer
|
||||||
*/
|
*/
|
||||||
public void setDatabaseConfigurer(EmbeddedDatabaseConfigurer configurer) {
|
public void setDatabaseConfigurer(EmbeddedDatabaseConfigurer configurer) {
|
||||||
|
Assert.notNull(configurer, "EmbeddedDatabaseConfigurer is required");
|
||||||
this.databaseConfigurer = configurer;
|
this.databaseConfigurer = configurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the strategy that will be used to populate the embedded database. Defaults to null.
|
* Set the strategy that will be used to populate the embedded database. Defaults to null.
|
||||||
* @param populator the database populator
|
* @param populator the database populator
|
||||||
*/
|
*/
|
||||||
public void setDatabasePopulator(DatabasePopulator populator) {
|
public void setDatabasePopulator(DatabasePopulator populator) {
|
||||||
Assert.notNull(populator, "The DatabasePopulator is required");
|
Assert.notNull(populator, "DatabasePopulator is required");
|
||||||
databasePopulator = populator;
|
this.databasePopulator = populator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the factory to use to create the DataSource instance that connects to the embedded database
|
* Set the factory to use to create the DataSource instance that connects to the embedded database.
|
||||||
* Defaults to {@link SimpleDriverDataSourceFactory}.
|
* Defaults to {@link SimpleDriverDataSourceFactory}.
|
||||||
* @param dataSourceFactory the data source factory
|
* @param dataSourceFactory the data source factory
|
||||||
*/
|
*/
|
||||||
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
|
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
|
||||||
Assert.notNull(dataSourceFactory, "The DataSourceFactory is required");
|
Assert.notNull(dataSourceFactory, "DataSourceFactory is required");
|
||||||
this.dataSourceFactory = dataSourceFactory;
|
this.dataSourceFactory = dataSourceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// other public methods
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method that returns the embedded database instance.
|
* Factory method that returns the embedded database instance.
|
||||||
*/
|
*/
|
||||||
public EmbeddedDatabase getDatabase() {
|
public EmbeddedDatabase getDatabase() {
|
||||||
if (dataSource == null) {
|
if (this.dataSource == null) {
|
||||||
initDatabase();
|
initDatabase();
|
||||||
}
|
}
|
||||||
return new EmbeddedDataSourceProxy(dataSource);
|
return new EmbeddedDataSourceProxy(this.dataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
// subclassing hooks
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook to initialize the embedded database. Subclasses may call to force initialization. After calling this method,
|
* Hook to initialize the embedded database. Subclasses may call to force initialization. After calling this method,
|
||||||
* {@link #getDataSource()} returns the DataSource providing connectivity to the db.
|
* {@link #getDataSource()} returns the DataSource providing connectivity to the db.
|
||||||
*/
|
*/
|
||||||
protected void initDatabase() {
|
protected void initDatabase() {
|
||||||
// create the embedded database source first
|
// Create the embedded database source first
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
logger.info("Created embedded database '" + databaseName + "'");
|
logger.info("Creating embedded database '" + this.databaseName + "'");
|
||||||
}
|
}
|
||||||
databaseConfigurer.configureConnectionProperties(dataSourceFactory.getConnectionProperties(), databaseName);
|
if (this.databaseConfigurer == null) {
|
||||||
dataSource = dataSourceFactory.getDataSource();
|
this.databaseConfigurer = EmbeddedDatabaseConfigurerFactory.getConfigurer(EmbeddedDatabaseType.HSQL);
|
||||||
if (databasePopulator != null) {
|
}
|
||||||
// now populate the database
|
this.databaseConfigurer.configureConnectionProperties(
|
||||||
|
this.dataSourceFactory.getConnectionProperties(), this.databaseName);
|
||||||
|
this.dataSource = this.dataSourceFactory.getDataSource();
|
||||||
|
|
||||||
|
// Now populate the database
|
||||||
|
if (this.databasePopulator != null) {
|
||||||
populateDatabase();
|
populateDatabase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void populateDatabase() {
|
||||||
|
try {
|
||||||
|
Connection connection = this.dataSource.getConnection();
|
||||||
|
try {
|
||||||
|
this.databasePopulator.populate(connection);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
catch (SQLException ex) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException ex) {
|
||||||
|
throw new DataAccessResourceFailureException("Failed to populate database", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook that gets the datasource that provides the connectivity to the embedded database.
|
* Hook that gets the DataSource that provides the connectivity to the embedded database.
|
||||||
* Returns null if the datasource has not been initialized or the database has been shutdown.
|
* <p>Returns null if the DataSource has not been initialized or the database has been shut down.
|
||||||
* Subclasses may call to access the datasource instance directly.
|
* Subclasses may call to access the datasource instance directly.
|
||||||
* @return the datasource
|
|
||||||
*/
|
*/
|
||||||
protected DataSource getDataSource() {
|
protected DataSource getDataSource() {
|
||||||
return dataSource;
|
return this.dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -155,68 +172,56 @@ public class EmbeddedDatabaseFactory {
|
||||||
* After calling, {@link #getDataSource()} returns null. Does nothing if no embedded database has been initialized.
|
* After calling, {@link #getDataSource()} returns null. Does nothing if no embedded database has been initialized.
|
||||||
*/
|
*/
|
||||||
protected void shutdownDatabase() {
|
protected void shutdownDatabase() {
|
||||||
if (dataSource != null) {
|
if (this.dataSource != null) {
|
||||||
databaseConfigurer.shutdown(dataSource, databaseName);
|
this.databaseConfigurer.shutdown(this.dataSource, this.databaseName);
|
||||||
dataSource = null;
|
this.dataSource = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal helper methods
|
|
||||||
|
|
||||||
private void populateDatabase() {
|
|
||||||
Connection connection = JdbcUtils.getConnection(dataSource);
|
|
||||||
try {
|
|
||||||
databasePopulator.populate(connection);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new RuntimeException("SQLException occurred populating embedded database", e);
|
|
||||||
} finally {
|
|
||||||
JdbcUtils.closeConnection(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class EmbeddedDataSourceProxy implements EmbeddedDatabase {
|
private class EmbeddedDataSourceProxy implements EmbeddedDatabase {
|
||||||
private DataSource dataSource;
|
|
||||||
|
private final DataSource dataSource;
|
||||||
|
|
||||||
public EmbeddedDataSourceProxy(DataSource dataSource) {
|
public EmbeddedDataSourceProxy(DataSource dataSource) {
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Connection getConnection() throws SQLException {
|
public Connection getConnection() throws SQLException {
|
||||||
return dataSource.getConnection();
|
return this.dataSource.getConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Connection getConnection(String username, String password) throws SQLException {
|
public Connection getConnection(String username, String password) throws SQLException {
|
||||||
return dataSource.getConnection(username, password);
|
return this.dataSource.getConnection(username, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLoginTimeout() throws SQLException {
|
public int getLoginTimeout() throws SQLException {
|
||||||
return dataSource.getLoginTimeout();
|
return this.dataSource.getLoginTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrintWriter getLogWriter() throws SQLException {
|
public PrintWriter getLogWriter() throws SQLException {
|
||||||
return dataSource.getLogWriter();
|
return this.dataSource.getLogWriter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoginTimeout(int seconds) throws SQLException {
|
public void setLoginTimeout(int seconds) throws SQLException {
|
||||||
dataSource.setLoginTimeout(seconds);
|
this.dataSource.setLoginTimeout(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLogWriter(PrintWriter out) throws SQLException {
|
public void setLogWriter(PrintWriter out) throws SQLException {
|
||||||
dataSource.setLogWriter(out);
|
this.dataSource.setLogWriter(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||||
return dataSource.isWrapperFor(iface);
|
return this.dataSource.isWrapperFor(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||||
return dataSource.unwrap(iface);
|
return this.dataSource.unwrap(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
shutdownDatabase();
|
shutdownDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
@ -24,18 +25,23 @@ import org.springframework.beans.factory.InitializingBean;
|
||||||
/**
|
/**
|
||||||
* A subclass of {@link EmbeddedDatabaseFactory} that implements {@link FactoryBean} for registration as a Spring bean.
|
* A subclass of {@link EmbeddedDatabaseFactory} that implements {@link FactoryBean} for registration as a Spring bean.
|
||||||
* Returns the actual {@link DataSource} that provides connectivity to the embedded database to Spring.
|
* Returns the actual {@link DataSource} that provides connectivity to the embedded database to Spring.
|
||||||
* The target DataSource is returned instead of a {@link EmbeddedDatabase} proxy since the FactoryBean will manage the initialization and destruction lifecycle of the database instance.
|
*
|
||||||
* Implements DisposableBean to shutdown the embedded database when the managing Spring container is shutdown.
|
* <p>The target DataSource is returned instead of a {@link EmbeddedDatabase} proxy since the FactoryBean
|
||||||
|
* will manage the initialization and destruction lifecycle of the database instance.
|
||||||
|
*
|
||||||
|
* <p>Implements DisposableBean to shutdown the embedded database when the managing Spring container is shutdown.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory implements FactoryBean<DataSource>, InitializingBean, DisposableBean {
|
public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory
|
||||||
|
implements FactoryBean<DataSource>, InitializingBean, DisposableBean {
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() {
|
||||||
initDatabase();
|
initDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataSource getObject() throws Exception {
|
public DataSource getObject() {
|
||||||
return getDataSource();
|
return getDataSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +53,7 @@ public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory impleme
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() throws Exception {
|
public void destroy() {
|
||||||
shutdownDatabase();
|
shutdownDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,18 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A supported embedded database type.
|
* A supported embedded database type.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public enum EmbeddedDatabaseType {
|
public enum EmbeddedDatabaseType {
|
||||||
HSQL, H2, DERBY;
|
|
||||||
|
HSQL, H2, DERBY
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
@ -20,7 +21,9 @@ import org.springframework.util.ClassUtils;
|
||||||
/**
|
/**
|
||||||
* Initializes an H2 embedded database instance.
|
* Initializes an H2 embedded database instance.
|
||||||
* Call {@link #getInstance()} to get the singleton instance of this class.
|
* Call {@link #getInstance()} to get the singleton instance of this class.
|
||||||
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
final class H2EmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfigurer {
|
final class H2EmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfigurer {
|
||||||
|
|
@ -42,15 +45,15 @@ final class H2EmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfigu
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private H2EmbeddedDatabaseConfigurer(Class<?> driverClass) {
|
||||||
|
this.driverClass = driverClass;
|
||||||
|
}
|
||||||
|
|
||||||
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
|
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
|
||||||
properties.setDriverClass(driverClass);
|
properties.setDriverClass(this.driverClass);
|
||||||
properties.setUrl(String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1", databaseName));
|
properties.setUrl(String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1", databaseName));
|
||||||
properties.setUsername("sa");
|
properties.setUsername("sa");
|
||||||
properties.setPassword("");
|
properties.setPassword("");
|
||||||
}
|
}
|
||||||
|
|
||||||
private H2EmbeddedDatabaseConfigurer(Class<?> driverClass) {
|
}
|
||||||
this.driverClass = driverClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
@ -20,6 +21,7 @@ import org.springframework.util.ClassUtils;
|
||||||
/**
|
/**
|
||||||
* Initializes an HSQL embedded database instance.
|
* Initializes an HSQL embedded database instance.
|
||||||
* Call {@link #getInstance()} to get the singleton instance of this class.
|
* Call {@link #getInstance()} to get the singleton instance of this class.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
@ -43,15 +45,15 @@ final class HsqlEmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfi
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HsqlEmbeddedDatabaseConfigurer(Class<?> driverClass) {
|
||||||
|
this.driverClass = driverClass;
|
||||||
|
}
|
||||||
|
|
||||||
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
|
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
|
||||||
properties.setDriverClass(driverClass);
|
properties.setDriverClass(this.driverClass);
|
||||||
properties.setUrl("jdbc:hsqldb:mem:" + databaseName);
|
properties.setUrl("jdbc:hsqldb:mem:" + databaseName);
|
||||||
properties.setUsername("sa");
|
properties.setUsername("sa");
|
||||||
properties.setPassword("");
|
properties.setPassword("");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsqlEmbeddedDatabaseConfigurer(Class<?> driverClass) {
|
|
||||||
this.driverClass = driverClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2009 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.embedded;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper JDBC utilities used by other classes in this package.
|
|
||||||
* Note there is some duplication here with JdbcUtils in jdbc.support package.
|
|
||||||
* We may want to consider simply using that at some point.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
final class JdbcUtils {
|
|
||||||
|
|
||||||
private static Log logger = LogFactory.getLog(EmbeddedDatabaseFactory.class);
|
|
||||||
|
|
||||||
private JdbcUtils() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Connection getConnection(DataSource dataSource) {
|
|
||||||
try {
|
|
||||||
return dataSource.getConnection();
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void closeConnection(Connection connection) {
|
|
||||||
if (connection != null) {
|
|
||||||
try {
|
|
||||||
connection.close();
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.debug("Could not close JDBC Connection", ex);
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
// We don't trust the JDBC driver: It might throw RuntimeException or Error.
|
|
||||||
logger.debug("Unexpected exception on closing JDBC Connection", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void closeStatement(Statement stmt) {
|
|
||||||
if (stmt != null) {
|
|
||||||
try {
|
|
||||||
stmt.close();
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.debug("Could not close JDBC Statement", ex);
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
// We don't trust the JDBC driver: It might throw RuntimeException or Error.
|
|
||||||
logger.debug("Unexpected exception on closing JDBC Statement", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -27,15 +28,17 @@ import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.EncodedResource;
|
import org.springframework.core.io.support.EncodedResource;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates a database from SQL scripts defined in external resources.
|
* Populates a database from SQL scripts defined in external resources.
|
||||||
* <p>
|
*
|
||||||
* Call {@link #addScript(Resource)} to add a SQL script location.<br>
|
* <p>Call {@link #addScript(Resource)} to add a SQL script location.<br>
|
||||||
* Call {@link #setSqlScriptEncoding(String)} to set the encoding for all added scripts.<br>
|
* Call {@link #setSqlScriptEncoding(String)} to set the encoding for all added scripts.<br>
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
|
|
@ -47,6 +50,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||||
|
|
||||||
private String sqlScriptEncoding;
|
private String sqlScriptEncoding;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a script to execute to populate the database.
|
* Add a script to execute to populate the database.
|
||||||
* @param script the path to a SQL script
|
* @param script the path to a SQL script
|
||||||
|
|
@ -65,15 +69,17 @@ 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.
|
||||||
* Note setting this property has no effect on added scripts that are already {@link EncodedResource encoded resources}.
|
* Note setting this property has no effect on added scripts that are already
|
||||||
|
* {@link EncodedResource encoded resources}.
|
||||||
* @see #addScript(Resource)
|
* @see #addScript(Resource)
|
||||||
*/
|
*/
|
||||||
public void setSqlScriptEncoding(String sqlScriptEncoding) {
|
public void setSqlScriptEncoding(String sqlScriptEncoding) {
|
||||||
this.sqlScriptEncoding = sqlScriptEncoding;
|
this.sqlScriptEncoding = sqlScriptEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void populate(Connection connection) throws SQLException {
|
public void populate(Connection connection) throws SQLException {
|
||||||
for (Resource script : scripts) {
|
for (Resource script : this.scripts) {
|
||||||
executeSqlScript(connection, applyEncodingIfNecessary(script), false);
|
executeSqlScript(connection, applyEncodingIfNecessary(script), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -81,8 +87,9 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||||
private EncodedResource applyEncodingIfNecessary(Resource script) {
|
private EncodedResource applyEncodingIfNecessary(Resource script) {
|
||||||
if (script instanceof EncodedResource) {
|
if (script instanceof EncodedResource) {
|
||||||
return (EncodedResource) script;
|
return (EncodedResource) script;
|
||||||
} else {
|
}
|
||||||
return new EncodedResource(script, sqlScriptEncoding);
|
else {
|
||||||
|
return new EncodedResource(script, this.sqlScriptEncoding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,6 +102,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||||
*/
|
*/
|
||||||
private void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError)
|
private void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
logger.info("Executing SQL script from " + resource);
|
logger.info("Executing SQL script from " + resource);
|
||||||
}
|
}
|
||||||
|
|
@ -112,25 +120,34 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||||
}
|
}
|
||||||
splitSqlScript(script, delimiter, statements);
|
splitSqlScript(script, delimiter, statements);
|
||||||
int lineNumber = 0;
|
int lineNumber = 0;
|
||||||
for (String statement : statements) {
|
Statement stmt = connection.createStatement();
|
||||||
lineNumber++;
|
try {
|
||||||
Statement stmt = null;
|
for (String statement : statements) {
|
||||||
try {
|
lineNumber++;
|
||||||
stmt = connection.createStatement();
|
try {
|
||||||
int rowsAffected = stmt.executeUpdate(statement);
|
int rowsAffected = stmt.executeUpdate(statement);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(rowsAffected + " rows affected by SQL: " + statement);
|
logger.debug(rowsAffected + " rows affected by SQL: " + statement);
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
if (continueOnError) {
|
|
||||||
if (logger.isWarnEnabled()) {
|
|
||||||
logger.warn("Line " + lineNumber + " statement failed: " + statement, e);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
} finally {
|
catch (SQLException ex) {
|
||||||
JdbcUtils.closeStatement(stmt);
|
if (continueOnError) {
|
||||||
|
if (logger.isWarnEnabled()) {
|
||||||
|
logger.warn("Line " + lineNumber + " statement failed: " + statement, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
stmt.close();
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
logger.debug("Could not close JDBC Statement", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long elapsedTime = System.currentTimeMillis() - startTime;
|
long elapsedTime = System.currentTimeMillis() - startTime;
|
||||||
|
|
@ -209,4 +226,4 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,35 +13,39 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.jdbc.datasource.embedded;
|
package org.springframework.jdbc.datasource.embedded;
|
||||||
|
|
||||||
|
import java.sql.Driver;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link SimpleDriverDataSource}.
|
* Creates a {@link SimpleDriverDataSource}.
|
||||||
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
final class SimpleDriverDataSourceFactory implements DataSourceFactory {
|
final class SimpleDriverDataSourceFactory implements DataSourceFactory {
|
||||||
|
|
||||||
private SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
|
private final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
|
||||||
|
|
||||||
public ConnectionProperties getConnectionProperties() {
|
public ConnectionProperties getConnectionProperties() {
|
||||||
return new ConnectionProperties() {
|
return new ConnectionProperties() {
|
||||||
public void setDriverClass(Class<?> driverClass) {
|
@SuppressWarnings("unchecked")
|
||||||
dataSource.setDriverClass(driverClass);
|
public void setDriverClass(Class driverClass) {
|
||||||
|
Assert.isAssignable(Driver.class, driverClass);
|
||||||
|
dataSource.setDriverClass((Class<? extends Driver>) driverClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUrl(String url) {
|
public void setUrl(String url) {
|
||||||
dataSource.setUrl(url);
|
dataSource.setUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsername(String username) {
|
public void setUsername(String username) {
|
||||||
dataSource.setUsername(username);
|
dataSource.setUsername(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPassword(String password) {
|
public void setPassword(String password) {
|
||||||
dataSource.setPassword(password);
|
dataSource.setPassword(password);
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +53,7 @@ final class SimpleDriverDataSourceFactory implements DataSourceFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataSource getDataSource() {
|
public DataSource getDataSource() {
|
||||||
return dataSource;
|
return this.dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue