SPR-6717: Added support for database destroy scripts

This commit is contained in:
David Syer
2011-06-06 07:28:25 +00:00
parent 97e047ed66
commit 6933a1af28
5 changed files with 111 additions and 22 deletions

View File

@@ -59,11 +59,12 @@ public class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefiniti
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));
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) {
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");
@@ -72,6 +73,14 @@ public class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefiniti
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);

View File

@@ -20,6 +20,7 @@ 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;
@@ -31,14 +32,15 @@ import org.springframework.util.Assert;
* @since 3.0
* @see DatabasePopulator
*/
public class DataSourceInitializer implements InitializingBean {
public class DataSourceInitializer implements InitializingBean, DisposableBean {
private DataSource dataSource;
private DatabasePopulator databasePopulator;
private boolean enabled = true;
private DatabasePopulator databaseCleaner;
private boolean enabled = true;
/**
* The {@link DataSource} to populate when this component is initialized.
@@ -58,6 +60,16 @@ public class DataSourceInitializer implements InitializingBean {
this.databasePopulator = databasePopulator;
}
/**
* 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) {
this.databaseCleaner = databaseCleaner;
}
/**
* Flag to explicitly enable or disable the database populator.
* @param enabled true if the database populator will be called on startup
@@ -66,30 +78,41 @@ public class DataSourceInitializer implements InitializingBean {
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);
}
}
/**
* 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(this.databasePopulator != null, "DatabasePopulator must be provided");
Assert.state(populator != null, "DatabasePopulator must be provided");
try {
Connection connection = this.dataSource.getConnection();
try {
this.databasePopulator.populate(connection);
}
finally {
populator.populate(connection);
} finally {
try {
connection.close();
}
catch (SQLException ex) {
} catch (SQLException ex) {
// ignore
}
}
}
catch (Exception ex) {
throw new DataAccessResourceFailureException("Failed to populate database", ex);
} catch (Exception ex) {
throw new DataAccessResourceFailureException("Failed to execute database script", ex);
}
}
}