jdbc:script's "separator" and "execution" attributes work nested with embedded-database as well; added "encoding" attribute to jdbc:script element; general revision of DatabasePopulator configuration and execution code

This commit is contained in:
Juergen Hoeller
2011-07-28 14:19:53 +00:00
parent 1baf2a3981
commit bbcf358a9d
19 changed files with 409 additions and 300 deletions

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2002-2011 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.config;
import java.util.Arrays;
import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.jdbc.datasource.init.CompositeDatabasePopulator;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
/**
* @author Juergen Hoeller
* @since 3.1
*/
class DatabasePopulatorConfigUtils {
public static void setDatabasePopulator(Element element, BeanDefinitionBuilder builder) {
List<Element> scripts = DomUtils.getChildElementsByTagName(element, "script");
if (scripts.size() > 0) {
builder.addPropertyValue("databasePopulator", createDatabasePopulator(element, scripts, "INIT"));
builder.addPropertyValue("databaseCleaner", createDatabasePopulator(element, scripts, "DESTROY"));
}
}
static private BeanDefinition createDatabasePopulator(Element element, List<Element> scripts, String execution) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CompositeDatabasePopulator.class);
boolean ignoreFailedDrops = element.getAttribute("ignore-failures").equals("DROPS");
boolean continueOnError = element.getAttribute("ignore-failures").equals("ALL");
ManagedList<BeanMetadataElement> delegates = new ManagedList<BeanMetadataElement>();
for (Element scriptElement : scripts) {
String executionAttr = scriptElement.getAttribute("execution");
if (!StringUtils.hasText(executionAttr)) {
executionAttr = "INIT";
}
if (!execution.equals(executionAttr)) {
continue;
}
BeanDefinitionBuilder delegate = BeanDefinitionBuilder.genericBeanDefinition(ResourceDatabasePopulator.class);
delegate.addPropertyValue("ignoreFailedDrops", ignoreFailedDrops);
delegate.addPropertyValue("continueOnError", continueOnError);
List<String> locations = Arrays.asList(scriptElement.getAttribute("location"));
// Use a factory bean for the resources so they can be given an order if a pattern is used
BeanDefinitionBuilder resourcesFactory = BeanDefinitionBuilder.genericBeanDefinition(SortedResourcesFactoryBean.class);
resourcesFactory.addConstructorArgValue(locations);
delegate.addPropertyValue("scripts", resourcesFactory.getBeanDefinition());
if (StringUtils.hasLength(scriptElement.getAttribute("encoding"))) {
delegate.addPropertyValue("sqlScriptEncoding", scriptElement.getAttribute("encoding"));
}
if (StringUtils.hasLength(scriptElement.getAttribute("separator"))) {
delegate.addPropertyValue("separator", scriptElement.getAttribute("separator"));
}
delegates.add(delegate.getBeanDefinition());
}
builder.addPropertyValue("populators", delegates);
return builder.getBeanDefinition();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -16,8 +16,7 @@
package org.springframework.jdbc.config;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
@@ -27,35 +26,32 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryBean;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses {@code embedded-database} element and
* creates a {@link BeanDefinition} for {@link EmbeddedDatabaseFactoryBean}. Picks up nested {@code script} elements and
* configures a {@link ResourceDatabasePopulator} for them.
*
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses an {@code embedded-database}
* element and creates a {@link BeanDefinition} for {@link EmbeddedDatabaseFactoryBean}. Picks up nested
* {@code script} elements and configures a {@link ResourceDatabasePopulator} for them.
*
* @author Oliver Gierke
* @author Juergen Hoeller
* @since 3.0
*/
class EmbeddedDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser {
private static final String NAME_PROPERTY = "databaseName";
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext context) {
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(EmbeddedDatabaseFactoryBean.class);
setDatabaseType(element, builder);
setDatabasePopulator(element, context, builder);
DatabasePopulatorConfigUtils.setDatabasePopulator(element, builder);
useIdAsDatabaseNameIfGiven(element, builder);
return getSourcedBeanDefinition(builder, element, context);
builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
return builder.getBeanDefinition();
}
private void useIdAsDatabaseNameIfGiven(Element element, BeanDefinitionBuilder builder) {
String id = element.getAttribute(ID_ATTRIBUTE);
if (StringUtils.hasText(id)) {
builder.addPropertyValue(NAME_PROPERTY, id);
builder.addPropertyValue("databaseName", id);
}
}
@@ -66,34 +62,4 @@ class EmbeddedDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser
}
}
private void setDatabasePopulator(Element element, ParserContext context, BeanDefinitionBuilder builder) {
List<Element> scripts = DomUtils.getChildElementsByTagName(element, "script");
if (scripts.size() > 0) {
builder.addPropertyValue("databasePopulator", createDatabasePopulator(scripts, context));
}
}
private BeanDefinition createDatabasePopulator(List<Element> scripts, ParserContext context) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ResourceDatabasePopulator.class);
List<String> locations = new ArrayList<String>();
for (Element scriptElement : scripts) {
locations.add(scriptElement.getAttribute("location"));
}
// Use a factory bean for the resources so they can be given an order if a pattern is used
BeanDefinitionBuilder resourcesFactory = BeanDefinitionBuilder
.genericBeanDefinition(SortedResourcesFactoryBean.class);
resourcesFactory.addConstructorArgValue(locations);
builder.addPropertyValue("scripts", resourcesFactory.getBeanDefinition());
return builder.getBeanDefinition();
}
private AbstractBeanDefinition getSourcedBeanDefinition(
BeanDefinitionBuilder builder, Element source, ParserContext context) {
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(context.extractSource(source));
return definition;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -16,39 +16,35 @@
package org.springframework.jdbc.config;
import java.util.Arrays;
import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.jdbc.datasource.init.CompositeDatabasePopulator;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses an {@code initialize-database} element and
* creates a {@link BeanDefinition} of type {@link DataSourceInitializer}. Picks up nested {@code script} elements and
* configures a {@link ResourceDatabasePopulator} for them.
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses an {@code initialize-database}
* element and creates a {@link BeanDefinition} of type {@link DataSourceInitializer}. Picks up nested
* {@code script} elements and configures a {@link ResourceDatabasePopulator} for them.
*
* @author Dave Syer
* @author Juergen Hoeller
* @since 3.0
*/
public class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser {
class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext context) {
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(DataSourceInitializer.class);
builder.addPropertyReference("dataSource", element.getAttribute("data-source"));
builder.addPropertyValue("enabled", element.getAttribute("enabled"));
setDatabasePopulator(element, context, builder);
return getSourcedBeanDefinition(builder, element, context);
DatabasePopulatorConfigUtils.setDatabasePopulator(element, builder);
builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
return builder.getBeanDefinition();
}
@Override
@@ -56,62 +52,4 @@ public class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefiniti
return true;
}
private void setDatabasePopulator(Element element, ParserContext context, BeanDefinitionBuilder builder) {
List<Element> scripts = DomUtils.getChildElementsByTagName(element, "script");
if (scripts.size() > 0) {
builder.addPropertyValue("databasePopulator", createDatabasePopulator(element, scripts, context, "INIT"));
builder.addPropertyValue("databaseCleaner", createDatabasePopulator(element, scripts, context, "DESTROY"));
}
}
private BeanDefinition createDatabasePopulator(Element element, List<Element> scripts, ParserContext context, String execution) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CompositeDatabasePopulator.class);
boolean ignoreFailedDrops = element.getAttribute("ignore-failures").equals("DROPS");
boolean continueOnError = element.getAttribute("ignore-failures").equals("ALL");
ManagedList<BeanMetadataElement> delegates = new ManagedList<BeanMetadataElement>();
for (Element scriptElement : scripts) {
String executionAttr = scriptElement.getAttribute("execution");
if (!StringUtils.hasText(executionAttr)) {
executionAttr = "INIT";
}
if (!execution.equals(executionAttr)) {
continue;
}
BeanDefinitionBuilder delegate = BeanDefinitionBuilder.genericBeanDefinition(ResourceDatabasePopulator.class);
delegate.addPropertyValue("ignoreFailedDrops", ignoreFailedDrops);
delegate.addPropertyValue("continueOnError", continueOnError);
List<String> locations = Arrays.asList(scriptElement.getAttribute("location"));
// Use a factory bean for the resources so they can be given an order if a pattern is used
BeanDefinitionBuilder resourcesFactory = BeanDefinitionBuilder
.genericBeanDefinition(SortedResourcesFactoryBean.class);
resourcesFactory.addConstructorArgValue(locations);
delegate.addPropertyValue("scripts", resourcesFactory.getBeanDefinition());
if (StringUtils.hasLength(scriptElement.getAttribute("separator"))) {
delegate.addPropertyValue("separator", scriptElement.getAttribute("separator"));
}
delegates.add(delegate.getBeanDefinition());
}
builder.addPropertyValue("populators", delegates);
return builder.getBeanDefinition();
}
private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source,
ParserContext context) {
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(context.extractSource(source));
return definition;
}
}

View File

@@ -25,8 +25,8 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.util.Assert;
/**
@@ -69,6 +69,15 @@ public class EmbeddedDatabaseFactory {
this.databaseName = databaseName;
}
/**
* Set the factory to use to create the DataSource instance that connects to the embedded database.
* <p>Defaults to {@link SimpleDriverDataSourceFactory}.
*/
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
Assert.notNull(dataSourceFactory, "DataSourceFactory is required");
this.dataSourceFactory = dataSourceFactory;
}
/**
* Set the type of embedded database to use. Call this when you wish to configure
* one of the pre-supported types. Defaults to HSQL.
@@ -80,33 +89,20 @@ public class EmbeddedDatabaseFactory {
/**
* 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
* <p>Call this when you wish to use an embedded database type not already supported.
*/
public void setDatabaseConfigurer(EmbeddedDatabaseConfigurer configurer) {
Assert.notNull(configurer, "EmbeddedDatabaseConfigurer is required");
this.databaseConfigurer = configurer;
}
/**
* Set the strategy that will be used to populate the embedded database. Defaults to null.
* @param populator the database populator
* @see org.springframework.jdbc.datasource.init.DataSourceInitializer#setDatabasePopulator
*/
public void setDatabasePopulator(DatabasePopulator populator) {
Assert.notNull(populator, "DatabasePopulator is required");
this.databasePopulator = populator;
}
/**
* 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, "DataSourceFactory is required");
this.dataSourceFactory = dataSourceFactory;
}
/**
* Factory method that returns the embedded database instance.
*/
@@ -137,7 +133,7 @@ public class EmbeddedDatabaseFactory {
// Now populate the database
if (this.databasePopulator != null) {
try {
populateDatabase();
DatabasePopulatorUtils.execute(this.databasePopulator, this.dataSource);
}
catch (RuntimeException ex) {
// failed to populate, so leave it as not initialized
@@ -147,35 +143,6 @@ public class EmbeddedDatabaseFactory {
}
}
private void populateDatabase() {
try {
Connection connection = this.dataSource.getConnection();
try {
this.databasePopulator.populate(connection);
}
finally {
try {
connection.close();
}
catch (SQLException ex) {
// ignore
}
}
}
catch (Exception ex) {
throw new DataAccessResourceFailureException("Failed to populate database", ex);
}
}
/**
* 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.
*/
protected DataSource getDataSource() {
return this.dataSource;
}
/**
* Hook to shutdown the embedded database. Subclasses may call to force shutdown.
* After calling, {@link #getDataSource()} returns null. Does nothing if no embedded database has been initialized.
@@ -187,6 +154,15 @@ public class EmbeddedDatabaseFactory {
}
}
/**
* Hook that gets the DataSource that provides the connectivity to the embedded database.
* <p>Returns <code>null</code> if the DataSource has not been initialized or the database
* has been shut down. Subclasses may call to access the DataSource instance directly.
*/
protected final DataSource getDataSource() {
return this.dataSource;
}
private class EmbeddedDataSourceProxy implements EmbeddedDatabase {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@ import javax.sql.DataSource;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
/**
* A subclass of {@link EmbeddedDatabaseFactory} that implements {@link FactoryBean} for registration as a Spring bean.
@@ -32,15 +34,38 @@ import org.springframework.beans.factory.InitializingBean;
* <p>Implements DisposableBean to shutdown the embedded database when the managing Spring container is shutdown.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
*/
public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory
implements FactoryBean<DataSource>, InitializingBean, DisposableBean {
private DatabasePopulator databaseCleaner;
/**
* Set a script execution to be run in the bean destruction callback,
* cleaning up the database and leaving it in a known state for others.
* @param databaseCleaner the database script executor to run on destroy
* @see #setDatabasePopulator
* @see org.springframework.jdbc.datasource.init.DataSourceInitializer#setDatabaseCleaner
*/
public void setDatabaseCleaner(DatabasePopulator databaseCleaner) {
this.databaseCleaner = databaseCleaner;
}
public void afterPropertiesSet() {
initDatabase();
}
public void destroy() {
if (this.databaseCleaner != null) {
DatabasePopulatorUtils.execute(this.databaseCleaner, getDataSource());
}
shutdownDatabase();
}
public DataSource getObject() {
return getDataSource();
}
@@ -53,8 +78,4 @@ public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory
return true;
}
public void destroy() {
shutdownDatabase();
}
}

View File

@@ -2,7 +2,6 @@
/**
*
* Provides extensible support for creating embedded database instances.
* HSQL in-memory support provided natively
*
*/
package org.springframework.jdbc.datasource.embedded;

View File

@@ -18,38 +18,40 @@ package org.springframework.jdbc.datasource.init;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* {@link DatabasePopulator} implementation that delegates to a list of other implementations, executing alll scripts.
*
* @author Dave Syer
* {@link DatabasePopulator} implementation that delegates to a list of other
* DatabasePopulator implementations, executing all scripts.
*
* @author Dave Syer
* @author Juergen Hoeller
* @since 3.1
*/
public class CompositeDatabasePopulator implements DatabasePopulator {
private List<DatabasePopulator> populators = new ArrayList<DatabasePopulator>();
/**
* @param populators the populators to set
* Specify a list of populators to delegate to.
*/
public void setPopulators(List<DatabasePopulator> populators) {
public void setPopulators(DatabasePopulator... populators) {
this.populators.clear();
this.populators.addAll(populators);
this.populators.addAll(Arrays.asList(populators));
}
/**
* @param populator the populator to add
* Add a populator to the list of delegates.
*/
public void addPopulator(DatabasePopulator populator) {
this.populators.add(populator);
public void addPopulators(DatabasePopulator... populators) {
this.populators.addAll(Arrays.asList(populators));
}
/* (non-Javadoc)
* @see org.springframework.jdbc.datasource.init.DatabasePopulator#populate(java.sql.Connection)
*/
public void populate(Connection connection) throws SQLException {
for (DatabasePopulator populator : populators) {
for (DatabasePopulator populator : this.populators) {
populator.populate(connection);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -16,14 +16,10 @@
package org.springframework.jdbc.datasource.init;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.Assert;
/**
* Used to populate a database during initialization.
@@ -42,6 +38,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
private boolean enabled = true;
/**
* The {@link DataSource} to populate when this component is initialized.
* Mandatory with no default.
@@ -61,9 +58,8 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
}
/**
* Set a script execution to be run in the bean destruction callback, cleaning up the database and leaving it in
* a known state for others.
*
* Set a script execution to be run in the bean destruction callback,
* cleaning up the database and leaving it in a known state for others.
* @param databaseCleaner the database script executor to run on destroy
*/
public void setDatabaseCleaner(DatabasePopulator databaseCleaner) {
@@ -78,42 +74,22 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
this.enabled = enabled;
}
/**
* Use the populator to set up data in the data source.
*/
public void afterPropertiesSet() throws Exception {
if (this.databasePopulator != null) {
execute(this.databasePopulator);
public void afterPropertiesSet() {
if (this.databasePopulator != null && this.enabled) {
DatabasePopulatorUtils.execute(this.databasePopulator, this.dataSource);
}
}
/**
* Use the populator to clean up data in the data source.
*/
public void destroy() throws Exception {
if (this.databaseCleaner != null) {
execute(this.databaseCleaner);
}
}
private void execute(DatabasePopulator populator) throws Exception {
if (this.enabled) {
Assert.state(this.dataSource != null, "DataSource must be provided");
Assert.state(populator != null, "DatabasePopulator must be provided");
try {
Connection connection = this.dataSource.getConnection();
try {
populator.populate(connection);
} finally {
try {
connection.close();
} catch (SQLException ex) {
// ignore
}
}
} catch (Exception ex) {
throw new DataAccessResourceFailureException("Failed to execute database script", ex);
}
public void destroy() {
if (this.databaseCleaner != null && this.enabled) {
DatabasePopulatorUtils.execute(this.databaseCleaner, this.dataSource);
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.init;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.Assert;
/**
* Utility methods for executing a DatabasePopulator.
*
* @author Juergen Hoeller
* @since 3.1
*/
public abstract class DatabasePopulatorUtils {
/**
* Execute the given DatabasePopulator against the given DataSource.
* @param populator the DatabasePopulator to execute
* @param dataSource the DataSource to execute against
*/
public static void execute(DatabasePopulator populator, DataSource dataSource) {
Assert.notNull(populator, "DatabasePopulator must be provided");
Assert.notNull(dataSource, "DataSource must be provided");
try {
Connection connection = dataSource.getConnection();
try {
populator.populate(connection);
}
finally {
try {
connection.close();
}
catch (SQLException ex) {
// ignore
}
}
}
catch (Exception ex) {
throw new DataAccessResourceFailureException("Failed to execute database script", ex);
}
}
}

View File

@@ -55,14 +55,14 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
private String sqlScriptEncoding;
private String separator;
private String commentPrefix = DEFAULT_COMMENT_PREFIX;
private boolean continueOnError = false;
private boolean ignoreFailedDrops = false;
private String separator = null;
/**
* Add a script to execute to populate the database.
@@ -90,6 +90,13 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
this.sqlScriptEncoding = sqlScriptEncoding;
}
/**
* Specify the statement separator, if a custom one.
*/
public void setSeparator(String separator) {
this.separator = separator;
}
/**
* Set the line prefix that identifies comments in the SQL script.
* Default is "--".
@@ -116,13 +123,6 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
this.ignoreFailedDrops = ignoreFailedDrops;
}
/**
* Specify the statement separator, if a custom one.
*/
public void setSeparator(String separator) {
this.separator = separator;
}
public void populate(Connection connection) throws SQLException {
for (Resource script : this.scripts) {

View File

@@ -0,0 +1,8 @@
/**
*
* Provides extensible support for initializing databases through scripts.
*
*/
package org.springframework.jdbc.datasource.init;