SPR-7604 - Support multiple embedded databases.

Embedded datasources now get their bean ids set as database name to allow multiple databases of the same type in parallel. Refactored tests a little and made BeanDefinitionParser package private to align with the other ones. Adapted changelog accordingly.
This commit is contained in:
Oliver Gierke 2010-10-02 06:30:05 +00:00
parent 5918e2fa9c
commit ba2bac17de
3 changed files with 51 additions and 19 deletions

View File

@ -18,6 +18,8 @@ Changes in version 3.0.5 (2010-10-13)
* AspectJExpressionPointcut uses bean ClassLoader for initializing the AspectJ pointcut parser
* JDBC bundle uses local ClassLoader as bean ClassLoader for "sql-error-codes.xml" parsing
* EmbeddedDatabaseFactory shuts down database when failing to populate it in "initDatabase()"
* embedded database support now also works with Derby >= 10.6
* "jdbc:embedded-database" uses id as database name to allow multiple ones in parallel
* DefaultLobHandler's "wrapAsLob" mode works with PostgreSQL's "getAsciiStream()" requirement
* ResultSetWrappingSqlRowSet (as used by JdbcTemplate's "queryForRowSet") supports column labels now
* LocalSessionFactoryBean's "entityCacheStrategies" works with region names on Hibernate 3.6 as well

View File

@ -38,16 +38,27 @@ import org.w3c.dom.Element;
* @author Oliver Gierke
* @since 3.0
*/
public class EmbeddedDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser {
class EmbeddedDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser {
private static final String NAME_PROPERTY = "databaseName";
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext context) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(EmbeddedDatabaseFactoryBean.class);
setDatabaseType(element, builder);
setDatabasePopulator(element, context, builder);
useIdAsDatabaseNameIfGiven(element, builder);
return getSourcedBeanDefinition(builder, element, context);
}
private void useIdAsDatabaseNameIfGiven(Element element, BeanDefinitionBuilder builder) {
String id = element.getAttribute(ID_ATTRIBUTE);
if (StringUtils.hasText(id)) {
builder.addPropertyValue(NAME_PROPERTY, id);
}
}
private void setDatabaseType(Element element, BeanDefinitionBuilder builder) {
String type = element.getAttribute("type");
if (StringUtils.hasText(type)) {

View File

@ -1,11 +1,18 @@
package org.springframework.jdbc.config;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
public class JdbcNamespaceIntegrationTest {
@ -14,13 +21,7 @@ public class JdbcNamespaceIntegrationTest {
public void testCreateEmbeddedDatabase() throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/jdbc/config/jdbc-config.xml");
try {
assertCorrectSetup(context.getBean("dataSource", DataSource.class));
assertCorrectSetup(context.getBean("h2DataSource", DataSource.class));
assertCorrectSetup(context.getBean("derbyDataSource", DataSource.class));
} finally {
context.close();
}
assertCorrectSetup(context, "dataSource", "h2DataSource", "derbyDataSource");
}
@Test
@ -28,26 +29,44 @@ public class JdbcNamespaceIntegrationTest {
// If Derby isn't cleaned up properly this will fail...
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/jdbc/config/jdbc-config.xml");
try {
assertCorrectSetup(context.getBean("derbyDataSource", DataSource.class));
} finally {
context.close();
}
assertCorrectSetup(context, "derbyDataSource");
}
@Test
public void testCreateWithResourcePattern() throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/jdbc/config/jdbc-config-pattern.xml");
assertCorrectSetup(context, "dataSource");
}
@Test
public void testMultipleDataSourcesHaveDifferentDatabaseNames() throws Exception {
DefaultListableBeanFactory factory = new XmlBeanFactory(new ClassPathResource(
"org/springframework/jdbc/config/jdbc-config-multiple-datasources.xml"));
assertBeanPropertyValueOf("databaseName", "firstDataSource", factory);
assertBeanPropertyValueOf("databaseName", "secondDataSource", factory);
}
private void assertBeanPropertyValueOf(String propertyName, String expected, DefaultListableBeanFactory factory) {
BeanDefinition bean = factory.getBeanDefinition(expected);
PropertyValue value = bean.getPropertyValues().getPropertyValue(propertyName);
assertThat(value, is(notNullValue()));
assertThat(value.getValue().toString(), is(expected));
}
private void assertCorrectSetup(ConfigurableApplicationContext context, String... dataSources) {
try {
assertCorrectSetup(context.getBean("dataSource", DataSource.class));
for (String dataSourceName : dataSources) {
DataSource dataSource = context.getBean(dataSourceName, DataSource.class);
JdbcTemplate t = new JdbcTemplate(dataSource);
assertEquals(1, t.queryForInt("select count(*) from T_TEST"));
}
} finally {
context.close();
}
}
private void assertCorrectSetup(DataSource dataSource) {
JdbcTemplate t = new JdbcTemplate(dataSource);
assertEquals(1, t.queryForInt("select count(*) from T_TEST"));
}
}