Browse Source

revised embedded database support

conversation
Juergen Hoeller 15 years ago
parent
commit
e9823b57b4
  1. 75
      org.springframework.core/src/main/java/org/springframework/core/io/ClassRelativeResourceLoader.java
  2. 6
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/SimpleDriverDataSource.java
  3. 21
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/AbstractEmbeddedDatabaseConfigurer.java
  4. 7
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/CannotReadScriptException.java
  5. 15
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/ConnectionProperties.java
  6. 15
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DataSourceFactory.java
  7. 5
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DatabasePopulator.java
  8. 51
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java
  9. 5
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java
  10. 85
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java
  11. 2
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurer.java
  12. 33
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java
  13. 143
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java
  14. 18
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBean.java
  15. 6
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseType.java
  16. 15
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/H2EmbeddedDatabaseConfigurer.java
  17. 12
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/HsqlEmbeddedDatabaseConfigurer.java
  18. 76
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/JdbcUtils.java
  19. 65
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/ResourceDatabasePopulator.java
  20. 18
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/SimpleDriverDataSourceFactory.java

75
org.springframework.core/src/main/java/org/springframework/core/io/ClassRelativeResourceLoader.java

@ -0,0 +1,75 @@ @@ -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);
}
}
}

6
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/SimpleDriverDataSource.java

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -107,8 +107,8 @@ public class SimpleDriverDataSource extends AbstractDriverBasedDataSource { @@ -107,8 +107,8 @@ public class SimpleDriverDataSource extends AbstractDriverBasedDataSource {
* within the SimpleDriverDataSource.
* @see #setDriver
*/
public void setDriverClass(Class driverClass) {
this.driver = (Driver) BeanUtils.instantiateClass(driverClass);
public void setDriverClass(Class<? extends Driver> driverClass) {
this.driver = BeanUtils.instantiateClass(driverClass);
}
/**

21
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/AbstractEmbeddedDatabaseConfigurer.java

@ -13,38 +13,39 @@ @@ -13,38 +13,39 @@
* 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;
/**
* Base class for {@link EmbeddedDatabaseConfigurer} implementations providing common shutdown behaviour.
* Base class for {@link EmbeddedDatabaseConfigurer} implementations providing common shutdown behavior.
*
* @author Oliver Gierke
* @author Juergen Hoeller
* @since 3.0
*/
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) {
Connection connection = JdbcUtils.getConnection(dataSource);
Statement stmt = null;
try {
stmt = connection.createStatement();
Connection connection = dataSource.getConnection();
Statement stmt = connection.createStatement();
stmt.execute("SHUTDOWN");
} catch (SQLException e) {
}
catch (SQLException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Could not shutdown embedded database", e);
logger.warn("Could not shutdown embedded database", ex);
}
} finally {
JdbcUtils.closeStatement(stmt);
}
}
}

7
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/CannotReadScriptException.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import org.springframework.core.io.support.EncodedResource;
@ -20,19 +21,19 @@ 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
* not be read during population.
*
* @author Keith Donald
* @since 3.0
*/
@SuppressWarnings("serial")
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 cause the underlying cause of the resource access failure
*/
public CannotReadScriptException(EncodedResource resource, Throwable cause) {
super("Cannot read SQL script from " + resource, cause);
}
}

15
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/ConnectionProperties.java

@ -13,38 +13,43 @@ @@ -13,38 +13,43 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import java.sql.Driver;
/**
* DataSourceFactory helper that allows essential JDBC connection properties to be configured consistently,
* independent of the actual DataSource implementation.
*
* @author Keith Donald
* @since 3.0
* @see DataSourceFactory
*/
public interface ConnectionProperties {
/**
* Set the JDBC driver to use to connect to the database.
* @param driverClass the jdbc driver class
*/
void setDriverClass(Class<?> driverClass);
void setDriverClass(Class driverClass);
/**
* Sets the JDBC connection URL of the database.
* @param url the connection url
*/
void setUrl(String url);
/**
* Sets the username to use to connect to the database.
* @param username the username
*/
void setUsername(String username);
/**
* Sets the password to use to connect to the database.
* @param password the password
*/
void setPassword(String password);
}

15
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DataSourceFactory.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import javax.sql.DataSource;
@ -20,21 +21,25 @@ import javax.sql.DataSource; @@ -20,21 +21,25 @@ import javax.sql.DataSource;
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.
* Call {@link #getConnectionProperties()} to configure normalized DataSource properties before calling {@link #getDataSource()} to actually get the configured DataSource instance.
* Encapsulates the creation of a particular DataSource implementation, such as a
* {@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
* @since 3.0
*/
public interface DataSourceFactory {
/**
* Allows properties of the DataSource to be configured.
*/
ConnectionProperties getConnectionProperties();
/**
* Returns the DataSource with the connection properties applied.
*/
DataSource getDataSource();
}

5
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DatabasePopulator.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import java.sql.Connection;
@ -20,6 +21,7 @@ import java.sql.SQLException; @@ -20,6 +21,7 @@ import java.sql.SQLException;
/**
* Strategy used to populate an embedded database during initialization.
*
* @author Keith Donald
* @since 3.0
* @see ResourceDatabasePopulator
@ -32,4 +34,5 @@ public interface DatabasePopulator { @@ -32,4 +34,5 @@ public interface DatabasePopulator {
* @throws SQLException if an unrecoverable data access exception occurs during database population
*/
void populate(Connection connection) throws SQLException;
}
}

51
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java

@ -13,26 +13,26 @@ @@ -13,26 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.derby.impl.io.VFMemoryStorageFactory;
import org.apache.derby.jdbc.EmbeddedDriver;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.util.ClassUtils;
/**
* {@link EmbeddedDatabaseConfigurer} for the Apache Derby database.
*
* @author Oliver Gierke
* @author Juergen Hoeller
* @since 3.0
*/
final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer {
@ -46,9 +46,6 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure @@ -46,9 +46,6 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure
private static DerbyEmbeddedDatabaseConfigurer INSTANCE;
private DerbyEmbeddedDatabaseConfigurer() {
}
/**
* Get the singleton {@link DerbyEmbeddedDatabaseConfigurer} instance.
* @return the configurer
@ -59,50 +56,48 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure @@ -59,50 +56,48 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure
// disable log file
System.setProperty("derby.stream.error.method",
DerbyEmbeddedDatabaseConfigurer.class.getName() + ".getNoopOutputStream");
ClassUtils.forName("org.apache.derby.jdbc.EmbeddedDriver", DerbyEmbeddedDatabaseConfigurer.class
.getClassLoader());
INSTANCE = new DerbyEmbeddedDatabaseConfigurer();
}
return INSTANCE;
}
private DerbyEmbeddedDatabaseConfigurer() {
}
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.setUsername("sa");
properties.setPassword("");
}
public void shutdown(DataSource dataSource, String databaseName) {
Connection connection = null;
try {
SimpleDriverDataSource shutdownDataSource = new SimpleDriverDataSource();
shutdownDataSource.setDriverClass(EmbeddedDriver.class);
shutdownDataSource.setUrl(String.format(URL_TEMPLATE, databaseName, "shutdown=true"));
connection = shutdownDataSource.getConnection();
} catch (SQLException e) {
if (SHUTDOWN_CODE.equals(e.getSQLState())) {
new EmbeddedDriver().connect(
String.format(URL_TEMPLATE, databaseName, "shutdown=true"), new Properties());
}
catch (SQLException ex) {
if (SHUTDOWN_CODE.equals(ex.getSQLState())) {
purgeDatabase(databaseName);
} else {
logger.warn("Could not shutdown in-memory Derby database", e);
}
} finally {
JdbcUtils.closeConnection(connection);
else {
logger.warn("Could not shutdown in-memory Derby database", ex);
}
}
}
/**
* Purges the in-memory database, to prevent it from hanging around after
* being shut down
* @param databaseName
* Purge the in-memory database, to prevent it from hanging around after
* being shut down.
*/
private void purgeDatabase(String databaseName) {
// 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)
try {
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 @@ -114,9 +109,9 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure
static OutputStream getNoopOutputStream() {
return new OutputStream() {
public void write(int b) throws IOException {
// ignore the input
// ignore the output
}
};
}
}
}

5
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import javax.sql.DataSource;
@ -21,13 +22,15 @@ import javax.sql.DataSource; @@ -21,13 +22,15 @@ import javax.sql.DataSource;
* A handle to an EmbeddedDatabase instance.
* Is a {@link DataSource}.
* Adds a shutdown operation so the embedded database instance can be shutdown.
*
* @author Keith Donald
* @since 3.0
*/
public interface EmbeddedDatabase extends DataSource {
/**
* Shutdown this embedded database.
*/
void shutdown();
}

85
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java

@ -13,39 +13,55 @@ @@ -13,39 +13,55 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.Resource;
import org.springframework.core.io.ResourceLoader;
/**
* A builder that provides a fluent API for constructing an embedded database.
* Usage example:
*
* <p>Usage example:
* <pre>
* EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
* EmbeddedDatabase db = builder.script("schema.sql").script("test-data.sql").build();
* db.shutdown();
* </pre>
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
*/
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() {
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
* Defaults to 'testdb' if not called.
@ -53,7 +69,7 @@ public class EmbeddedDatabaseBuilder { @@ -53,7 +69,7 @@ public class EmbeddedDatabaseBuilder {
* @return this, for fluent call chaining
*/
public EmbeddedDatabaseBuilder name(String databaseName) {
databaseFactory.setDatabaseName(databaseName);
this.databaseFactory.setDatabaseName(databaseName);
return this;
}
@ -64,7 +80,7 @@ public class EmbeddedDatabaseBuilder { @@ -64,7 +80,7 @@ public class EmbeddedDatabaseBuilder {
* @return this, for fluent call chaining
*/
public EmbeddedDatabaseBuilder type(EmbeddedDatabaseType databaseType) {
databaseFactory.setDatabaseType(databaseType);
this.databaseFactory.setDatabaseType(databaseType);
return this;
}
@ -74,7 +90,7 @@ public class EmbeddedDatabaseBuilder { @@ -74,7 +90,7 @@ public class EmbeddedDatabaseBuilder {
* @return this, for fluent call chaining
*/
public EmbeddedDatabaseBuilder script(String sqlResource) {
databasePopulator.addScript(resourceLoader.getResource(sqlResource));
this.databasePopulator.addScript(resourceLoader.getResource(sqlResource));
return this;
}
@ -83,45 +99,28 @@ public class EmbeddedDatabaseBuilder { @@ -83,45 +99,28 @@ public class EmbeddedDatabaseBuilder {
* @return the embedded database
*/
public EmbeddedDatabase build() {
return 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);
return this.databaseFactory.getDatabase();
}
/**
* 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
*/
public static EmbeddedDatabase buildDefault() {
return new EmbeddedDatabaseBuilder().script("schema.sql").script("test-data.sql").build();
}
private EmbeddedDatabaseBuilder(ResourceLoader loader) {
init(loader);
}
private void init(ResourceLoader loader) {
databaseFactory = new EmbeddedDatabaseFactory();
databasePopulator = new ResourceDatabasePopulator();
databaseFactory.setDatabasePopulator(databasePopulator);
resourceLoader = loader;
/**
* 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(Class clazz) {
return new EmbeddedDatabaseBuilder(new ClassRelativeResourceLoader(clazz));
}
}

2
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurer.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import javax.sql.DataSource;
@ -20,6 +21,7 @@ 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.
* Create a implementation for each database type you wish to support; for example HSQL, H2, or some other type.
*
* @author Keith Donald
* @since 3.0
*/

33
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java

@ -13,13 +13,15 @@ @@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import org.springframework.util.Assert;
/**
* Maps well-known {@link EmbeddedDatabaseType embedded database types} to {@link EmbeddedDatabaseConfigurer}
* strategies.
* Maps well-known {@link EmbeddedDatabaseType embedded database types} to
* {@link EmbeddedDatabaseConfigurer} strategies.
*
* @author Keith Donald
* @author Oliver Gierke
* @since 3.0
@ -27,25 +29,26 @@ import org.springframework.util.Assert; @@ -27,25 +29,26 @@ import org.springframework.util.Assert;
final class EmbeddedDatabaseConfigurerFactory {
public static EmbeddedDatabaseConfigurer getConfigurer(EmbeddedDatabaseType type) throws IllegalStateException {
Assert.notNull(type, "The EmbeddedDatabaseType is required");
Assert.notNull(type, "EmbeddedDatabaseType is required");
try {
switch (type) {
case HSQL:
return HsqlEmbeddedDatabaseConfigurer.getInstance();
case H2:
return H2EmbeddedDatabaseConfigurer.getInstance();
case DERBY:
return DerbyEmbeddedDatabaseConfigurer.getInstance();
default:
throw new UnsupportedOperationException("Other embedded database types not yet supported");
case HSQL:
return HsqlEmbeddedDatabaseConfigurer.getInstance();
case H2:
return H2EmbeddedDatabaseConfigurer.getInstance();
case DERBY:
return DerbyEmbeddedDatabaseConfigurer.getInstance();
default:
throw new UnsupportedOperationException("Other embedded database types not yet supported");
}
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Drivers for test database type [" + type
+ "] are not available in the classpath", e);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException("Driver for test database type [" + type +
"] is not available in the classpath", ex);
}
}
private EmbeddedDatabaseConfigurerFactory() {
}
}
}

143
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java

@ -13,39 +13,43 @@ @@ -13,39 +13,43 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.Assert;
/**
* Creates a {@link EmbeddedDatabase} instance. Callers are guaranteed that the returned database has been fully
* 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 #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 #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 #getDatabase()} to get the {@link EmbeddedDatabase} instance.<br>
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
*/
public class EmbeddedDatabaseFactory {
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;
@ -53,101 +57,114 @@ public class EmbeddedDatabaseFactory { @@ -53,101 +57,114 @@ public class EmbeddedDatabaseFactory {
private DataSource dataSource;
/**
* Creates a default {@link EmbeddedDatabaseFactory}.
* Calling {@link #getDatabase()} will create a embedded HSQL database of name 'testdb'.
*/
public EmbeddedDatabaseFactory() {
setDatabaseName("testdb");
setDatabaseType(EmbeddedDatabaseType.HSQL);
setDataSourceFactory(new SimpleDriverDataSourceFactory());
}
/**
* Sets the name of the database. Defaults to 'testdb'.
* @param name of the test database
* Set the name of the database. Defaults to "testdb".
* @param databaseName name of the test database
*/
public void setDatabaseName(String name) {
Assert.notNull(name, "The testDatabaseName is required");
databaseName = name;
public void setDatabaseName(String databaseName) {
Assert.notNull(databaseName, "Database name is required");
this.databaseName = databaseName;
}
/**
* Sets the type of embedded database to use. Call this when you wish to configure one of the pre-supported types.
* Defaults to HSQL.
* Set 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
*/
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.
* @param configurer the embedded database configurer
*/
public void setDatabaseConfigurer(EmbeddedDatabaseConfigurer configurer) {
Assert.notNull(configurer, "EmbeddedDatabaseConfigurer is required");
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
*/
public void setDatabasePopulator(DatabasePopulator populator) {
Assert.notNull(populator, "The DatabasePopulator is required");
databasePopulator = populator;
Assert.notNull(populator, "DatabasePopulator is required");
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}.
* @param dataSourceFactory the data source factory
*/
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
Assert.notNull(dataSourceFactory, "The DataSourceFactory is required");
Assert.notNull(dataSourceFactory, "DataSourceFactory is required");
this.dataSourceFactory = dataSourceFactory;
}
// other public methods
/**
* Factory method that returns the embedded database instance.
*/
public EmbeddedDatabase getDatabase() {
if (dataSource == null) {
if (this.dataSource == null) {
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,
* {@link #getDataSource()} returns the DataSource providing connectivity to the db.
*/
protected void initDatabase() {
// create the embedded database source first
// Create the embedded database source first
if (logger.isInfoEnabled()) {
logger.info("Created embedded database '" + databaseName + "'");
logger.info("Creating embedded database '" + this.databaseName + "'");
}
databaseConfigurer.configureConnectionProperties(dataSourceFactory.getConnectionProperties(), databaseName);
dataSource = dataSourceFactory.getDataSource();
if (databasePopulator != null) {
// now populate the database
if (this.databaseConfigurer == null) {
this.databaseConfigurer = EmbeddedDatabaseConfigurerFactory.getConfigurer(EmbeddedDatabaseType.HSQL);
}
this.databaseConfigurer.configureConnectionProperties(
this.dataSourceFactory.getConnectionProperties(), this.databaseName);
this.dataSource = this.dataSourceFactory.getDataSource();
// Now populate the database
if (this.databasePopulator != null) {
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.
* Returns null if the datasource has not been initialized or the database has been shutdown.
* Hook that gets the DataSource that provides the connectivity to the embedded database.
* <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.
* @return the datasource
*/
protected DataSource getDataSource() {
return dataSource;
return this.dataSource;
}
/**
@ -155,68 +172,56 @@ public class EmbeddedDatabaseFactory { @@ -155,68 +172,56 @@ public class EmbeddedDatabaseFactory {
* After calling, {@link #getDataSource()} returns null. Does nothing if no embedded database has been initialized.
*/
protected void shutdownDatabase() {
if (dataSource != null) {
databaseConfigurer.shutdown(dataSource, databaseName);
dataSource = null;
if (this.dataSource != null) {
this.databaseConfigurer.shutdown(this.dataSource, this.databaseName);
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 DataSource dataSource;
private final DataSource dataSource;
public EmbeddedDataSourceProxy(DataSource dataSource) {
this.dataSource = dataSource;
}
public Connection getConnection() throws SQLException {
return dataSource.getConnection();
return this.dataSource.getConnection();
}
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 {
return dataSource.getLoginTimeout();
return this.dataSource.getLoginTimeout();
}
public PrintWriter getLogWriter() throws SQLException {
return dataSource.getLogWriter();
return this.dataSource.getLogWriter();
}
public void setLoginTimeout(int seconds) throws SQLException {
dataSource.setLoginTimeout(seconds);
this.dataSource.setLoginTimeout(seconds);
}
public void setLogWriter(PrintWriter out) throws SQLException {
dataSource.setLogWriter(out);
this.dataSource.setLogWriter(out);
}
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 {
return dataSource.unwrap(iface);
return this.dataSource.unwrap(iface);
}
public void shutdown() {
shutdownDatabase();
}
}
}
}

18
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBean.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import javax.sql.DataSource;
@ -24,18 +25,23 @@ import org.springframework.beans.factory.InitializingBean; @@ -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.
* 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
* @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();
}
public DataSource getObject() throws Exception {
public DataSource getObject() {
return getDataSource();
}
@ -47,7 +53,7 @@ public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory impleme @@ -47,7 +53,7 @@ public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory impleme
return true;
}
public void destroy() throws Exception {
public void destroy() {
shutdownDatabase();
}

6
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseType.java

@ -13,14 +13,18 @@ @@ -13,14 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
/**
* A supported embedded database type.
*
* @author Keith Donald
* @author Oliver Gierke
* @since 3.0
*/
public enum EmbeddedDatabaseType {
HSQL, H2, DERBY;
HSQL, H2, DERBY
}

15
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/H2EmbeddedDatabaseConfigurer.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import org.springframework.util.ClassUtils;
@ -20,7 +21,9 @@ import org.springframework.util.ClassUtils; @@ -20,7 +21,9 @@ import org.springframework.util.ClassUtils;
/**
* Initializes an H2 embedded database instance.
* Call {@link #getInstance()} to get the singleton instance of this class.
*
* @author Oliver Gierke
* @author Juergen Hoeller
* @since 3.0
*/
final class H2EmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfigurer {
@ -42,15 +45,15 @@ final class H2EmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfigu @@ -42,15 +45,15 @@ final class H2EmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfigu
return INSTANCE;
}
private H2EmbeddedDatabaseConfigurer(Class<?> driverClass) {
this.driverClass = driverClass;
}
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.setUsername("sa");
properties.setPassword("");
}
private H2EmbeddedDatabaseConfigurer(Class<?> driverClass) {
this.driverClass = driverClass;
}
}
}

12
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/HsqlEmbeddedDatabaseConfigurer.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import org.springframework.util.ClassUtils;
@ -20,6 +21,7 @@ import org.springframework.util.ClassUtils; @@ -20,6 +21,7 @@ import org.springframework.util.ClassUtils;
/**
* Initializes an HSQL embedded database instance.
* Call {@link #getInstance()} to get the singleton instance of this class.
*
* @author Keith Donald
* @author Oliver Gierke
* @since 3.0
@ -43,15 +45,15 @@ final class HsqlEmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfi @@ -43,15 +45,15 @@ final class HsqlEmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfi
return INSTANCE;
}
private HsqlEmbeddedDatabaseConfigurer(Class<?> driverClass) {
this.driverClass = driverClass;
}
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
properties.setDriverClass(driverClass);
properties.setDriverClass(this.driverClass);
properties.setUrl("jdbc:hsqldb:mem:" + databaseName);
properties.setUsername("sa");
properties.setPassword("");
}
private HsqlEmbeddedDatabaseConfigurer(Class<?> driverClass) {
this.driverClass = driverClass;
}
}

76
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/JdbcUtils.java

@ -1,76 +0,0 @@ @@ -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);
}
}
}
}

65
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/ResourceDatabasePopulator.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import java.io.IOException;
@ -27,15 +28,17 @@ import java.util.List; @@ -27,15 +28,17 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.util.StringUtils;
/**
* 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>
*
* @author Keith Donald
* @since 3.0
*/
@ -47,6 +50,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator { @@ -47,6 +50,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
private String sqlScriptEncoding;
/**
* Add a script to execute to populate the database.
* @param script the path to a SQL script
@ -65,15 +69,17 @@ public class ResourceDatabasePopulator implements DatabasePopulator { @@ -65,15 +69,17 @@ 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 setting this property has no effect on added scripts that are already
* {@link EncodedResource encoded resources}.
* @see #addScript(Resource)
*/
public void setSqlScriptEncoding(String sqlScriptEncoding) {
this.sqlScriptEncoding = sqlScriptEncoding;
}
public void populate(Connection connection) throws SQLException {
for (Resource script : scripts) {
for (Resource script : this.scripts) {
executeSqlScript(connection, applyEncodingIfNecessary(script), false);
}
}
@ -81,8 +87,9 @@ public class ResourceDatabasePopulator implements DatabasePopulator { @@ -81,8 +87,9 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
private EncodedResource applyEncodingIfNecessary(Resource script) {
if (script instanceof EncodedResource) {
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 { @@ -95,6 +102,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
*/
private void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError)
throws SQLException {
if (logger.isInfoEnabled()) {
logger.info("Executing SQL script from " + resource);
}
@ -112,25 +120,34 @@ public class ResourceDatabasePopulator implements DatabasePopulator { @@ -112,25 +120,34 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
}
splitSqlScript(script, delimiter, statements);
int lineNumber = 0;
for (String statement : statements) {
lineNumber++;
Statement stmt = null;
try {
stmt = connection.createStatement();
int rowsAffected = stmt.executeUpdate(statement);
if (logger.isDebugEnabled()) {
logger.debug(rowsAffected + " rows affected by SQL: " + statement);
Statement stmt = connection.createStatement();
try {
for (String statement : statements) {
lineNumber++;
try {
int rowsAffected = stmt.executeUpdate(statement);
if (logger.isDebugEnabled()) {
logger.debug(rowsAffected + " rows affected by SQL: " + statement);
}
}
} catch (SQLException e) {
if (continueOnError) {
if (logger.isWarnEnabled()) {
logger.warn("Line " + lineNumber + " statement failed: " + statement, e);
catch (SQLException ex) {
if (continueOnError) {
if (logger.isWarnEnabled()) {
logger.warn("Line " + lineNumber + " statement failed: " + statement, ex);
}
}
else {
throw ex;
}
} else {
throw e;
}
} finally {
JdbcUtils.closeStatement(stmt);
}
}
finally {
try {
stmt.close();
}
catch (Throwable ex) {
logger.debug("Could not close JDBC Statement", ex);
}
}
long elapsedTime = System.currentTimeMillis() - startTime;
@ -209,4 +226,4 @@ public class ResourceDatabasePopulator implements DatabasePopulator { @@ -209,4 +226,4 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
}
}
}
}

18
org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/SimpleDriverDataSourceFactory.java

@ -13,35 +13,39 @@ @@ -13,35 +13,39 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded;
import java.sql.Driver;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.util.Assert;
/**
* Creates a {@link SimpleDriverDataSource}.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
*/
final class SimpleDriverDataSourceFactory implements DataSourceFactory {
private SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
private final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
public ConnectionProperties getConnectionProperties() {
return new ConnectionProperties() {
public void setDriverClass(Class<?> driverClass) {
dataSource.setDriverClass(driverClass);
@SuppressWarnings("unchecked")
public void setDriverClass(Class driverClass) {
Assert.isAssignable(Driver.class, driverClass);
dataSource.setDriverClass((Class<? extends Driver>) driverClass);
}
public void setUrl(String url) {
dataSource.setUrl(url);
}
public void setUsername(String username) {
dataSource.setUsername(username);
}
public void setPassword(String password) {
dataSource.setPassword(password);
}
@ -49,7 +53,7 @@ final class SimpleDriverDataSourceFactory implements DataSourceFactory { @@ -49,7 +53,7 @@ final class SimpleDriverDataSourceFactory implements DataSourceFactory {
}
public DataSource getDataSource() {
return dataSource;
return this.dataSource;
}
}

Loading…
Cancel
Save