Browse Source

RESOLVED - issue SPR-5917: DataSourceInitializer and namespace support for creating and populating databases

Tweak initializer to allow placeholders for script locations
pull/23217/head
David Syer 15 years ago
parent
commit
747f71f9d2
  1. 83
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/config/InitializeDatabaseBeanDefinitionParser.java
  2. 7
      org.springframework.jdbc/src/test/java/org/springframework/jdbc/config/InitializeDatabaseIntegrationTest.java
  3. 25
      org.springframework.jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-initialize-placeholder-config.xml

83
org.springframework.jdbc/src/main/java/org/springframework/jdbc/config/InitializeDatabaseBeanDefinitionParser.java

@ -23,6 +23,7 @@ import java.util.Collections; @@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@ -32,7 +33,6 @@ import org.springframework.core.io.Resource; @@ -32,7 +33,6 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
@ -67,17 +67,54 @@ public class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefiniti @@ -67,17 +67,54 @@ public class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefiniti
}
}
private DatabasePopulator createDatabasePopulator(Element element, List<Element> scripts, ParserContext context) {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setIgnoreFailedDrops(element.getAttribute("ignore-failures").equals("DROPS"));
populator.setContinueOnError(element.getAttribute("ignore-failures").equals("ALL"));
private BeanDefinition createDatabasePopulator(Element element, List<Element> scripts, ParserContext context) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ResourceDatabasePopulator.class);
builder.addPropertyValue("ignoreFailedDrops", element.getAttribute("ignore-failures").equals("DROPS"));
builder.addPropertyValue("continueOnError", element.getAttribute("ignore-failures").equals("ALL"));
List<String> locations = new ArrayList<String>();
for (Element scriptElement : scripts) {
String location = scriptElement.getAttribute("location");
ResourceLoader resourceLoader = context.getReaderContext().getResourceLoader();
if (resourceLoader instanceof ResourcePatternResolver) {
try {
List<Resource> resources = new ArrayList<Resource>(Arrays.asList(((ResourcePatternResolver)resourceLoader).getResources(location)));
Collections.<Resource>sort(resources, new Comparator<Resource>() {
locations.add(location);
}
// Use a factor bean for the resources so they can be given an order if a pattern is used
BeanDefinitionBuilder resourcesFactory = BeanDefinitionBuilder
.genericBeanDefinition(SortedResourcesFactoryBean.class);
resourcesFactory.addConstructorArgValue(context.getReaderContext().getResourceLoader());
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;
}
public static class SortedResourcesFactoryBean implements FactoryBean<Resource[]> {
private ResourceLoader resourceLoader;
private List<String> locations;
public SortedResourcesFactoryBean(ResourceLoader resourceLoader, List<String> locations) {
super();
this.resourceLoader = resourceLoader;
this.locations = locations;
}
public Resource[] getObject() throws Exception {
List<Resource> scripts = new ArrayList<Resource>();
for (String location : locations) {
if (resourceLoader instanceof ResourcePatternResolver) {
List<Resource> resources = new ArrayList<Resource>(Arrays
.asList(((ResourcePatternResolver) resourceLoader).getResources(location)));
Collections.<Resource> sort(resources, new Comparator<Resource>() {
public int compare(Resource o1, Resource o2) {
try {
return o1.getURL().toString().compareTo(o2.getURL().toString());
@ -87,23 +124,25 @@ public class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefiniti @@ -87,23 +124,25 @@ public class InitializeDatabaseBeanDefinitionParser extends AbstractBeanDefiniti
}
});
for (Resource resource : resources) {
populator.addScript(resource);
scripts.add(resource);
}
} catch (IOException e) {
context.getReaderContext().error("Cannot locate resources for script from location="+location, scriptElement);
} else {
scripts.add(resourceLoader.getResource(location));
}
} else {
populator.addScript(resourceLoader.getResource(location));
}
return scripts.toArray(new Resource[scripts.size()]);
}
public Class<? extends Resource[]> getObjectType() {
// TODO Auto-generated method stub
return null;
}
public boolean isSingleton() {
// TODO Auto-generated method stub
return false;
}
return populator;
}
private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source,
ParserContext context) {
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(context.extractSource(source));
return definition;
}
}

7
org.springframework.jdbc/src/test/java/org/springframework/jdbc/config/InitializeDatabaseIntegrationTest.java

@ -65,6 +65,13 @@ public class InitializeDatabaseIntegrationTest { @@ -65,6 +65,13 @@ public class InitializeDatabaseIntegrationTest {
assertEquals("Dave", t.queryForObject("select name from T_TEST", String.class));
}
@Test
public void testScriptNameWithPlaceholder() throws Exception {
context = new ClassPathXmlApplicationContext("org/springframework/jdbc/config/jdbc-initialize-placeholder-config.xml");
DataSource dataSource = context.getBean("dataSource", DataSource.class);
assertCorrectSetup(dataSource);
}
@Test
public void testCacheInitialization() throws Exception {
context = new ClassPathXmlApplicationContext("org/springframework/jdbc/config/jdbc-initialize-cache-config.xml");

25
org.springframework.jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-initialize-placeholder-config.xml

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
<jdbc:embedded-database id="dataSource" type="HSQL" />
<jdbc:initialize-database data-source="dataSource" enabled="${data.source.init}">
<jdbc:script location="${schema.scripts}" />
<jdbc:script location="${insert.scripts}" />
</jdbc:initialize-database>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties">
<value>
schema.scripts=classpath:org/springframework/jdbc/config/db-schema.sql
insert.scripts=classpath:org/springframework/jdbc/config/*-data.sql
data.source.init=true
</value>
</property>
</bean>
</beans>
Loading…
Cancel
Save