diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/config/EmbeddedDatabaseBeanDefinitionParser.java b/spring-jdbc/src/main/java/org/springframework/jdbc/config/EmbeddedDatabaseBeanDefinitionParser.java index 5093a52732b..5f7abbe080f 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/config/EmbeddedDatabaseBeanDefinitionParser.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/config/EmbeddedDatabaseBeanDefinitionParser.java @@ -48,10 +48,16 @@ class EmbeddedDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser */ static final String DB_NAME_ATTRIBUTE = "database-name"; + /** + * Constant for the "generate-name" attribute. + */ + static final String GENERATE_NAME_ATTRIBUTE = "generate-name"; + @Override protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(EmbeddedDatabaseFactoryBean.class); + setGenerateUniqueDatabaseNameFlag(element, builder); setDatabaseName(element, builder); setDatabaseType(element, builder); DatabasePopulatorConfigUtils.setDatabasePopulator(element, builder); @@ -64,6 +70,13 @@ class EmbeddedDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser return true; } + private void setGenerateUniqueDatabaseNameFlag(Element element, BeanDefinitionBuilder builder) { + String generateName = element.getAttribute(GENERATE_NAME_ATTRIBUTE); + if (StringUtils.hasText(generateName)) { + builder.addPropertyValue("generateUniqueDatabaseName", generateName); + } + } + private void setDatabaseName(Element element, BeanDefinitionBuilder builder) { // 1) Check for an explicit database name String name = element.getAttribute(DB_NAME_ATTRIBUTE); @@ -76,8 +89,7 @@ class EmbeddedDatabaseBeanDefinitionParser extends AbstractBeanDefinitionParser if (StringUtils.hasText(name)) { builder.addPropertyValue("databaseName", name); } - - // 3) Let EmbeddedDatabaseFactory set the default "testdb" name + // else, let EmbeddedDatabaseFactory use the default "testdb" name } private void setDatabaseType(Element element, BeanDefinitionBuilder builder) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java index 6c5ad88f826..e0c340fedaf 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -23,7 +23,7 @@ import javax.sql.DataSource; * *
An {@code EmbeddedDatabase} is also a {@link DataSource} and adds a * {@link #shutdown} operation so that the embedded database instance can be - * shutdown. + * shut down gracefully. * * @author Keith Donald * @author Sam Brannen @@ -32,7 +32,7 @@ import javax.sql.DataSource; public interface EmbeddedDatabase extends DataSource { /** - * Shutdown this embedded database. + * Shut down this embedded database. */ void shutdown(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java index 8e94ae3b521..13f66dcd5b1 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -78,12 +78,32 @@ public class EmbeddedDatabaseBuilder { this.resourceLoader = resourceLoader; } + /** + * Specify whether a unique ID should be generated and used as the database name. + *
If the configuration for this builder is reused across multiple + * application contexts within a single JVM, this flag should be enabled + * (i.e., set to {@code true}) in order to ensure that each application context + * gets its own embedded database. + *
Enabling this flag overrides any explicit name set via {@link #setName}. + * @param flag {@code true} if a unique database name should be generated + * @return {@code this}, to facilitate method chaining + * @see #setName + * @since 4.2 + */ + public EmbeddedDatabaseBuilder generateUniqueName(boolean flag) { + this.databaseFactory.setGenerateUniqueDatabaseName(flag); + return this; + } + /** * Set the name of the embedded database. *
Defaults to {@link EmbeddedDatabaseFactory#DEFAULT_DATABASE_NAME} if * not called. + *
Will be overridden if the {@code generateUniqueName} flag has been + * set to {@code true}. * @param databaseName the name of the embedded database to build * @return {@code this}, to facilitate method chaining + * @see #generateUniqueName */ public EmbeddedDatabaseBuilder setName(String databaseName) { this.databaseFactory.setDatabaseName(databaseName); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java index 9ce946ee76e..0b4f43c0356 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -19,7 +19,9 @@ package org.springframework.jdbc.datasource.embedded; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; +import java.util.UUID; import java.util.logging.Logger; + import javax.sql.DataSource; import org.apache.commons.logging.Log; @@ -30,25 +32,28 @@ import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; import org.springframework.util.Assert; /** - * Factory for creating {@link EmbeddedDatabase} instances. + * Factory for creating an {@link EmbeddedDatabase} instance. * - *
Callers are guaranteed that a returned database has been fully initialized - * and populated. + *
Callers are guaranteed that the returned database has been fully + * initialized and populated. * - *
Can be configured: + *
The factory can be configured as follows: *
Call {@link #getDatabase()} to get the {@link EmbeddedDatabase} instance. + *
After configuring the factory, call {@link #getDatabase()} to obtain + * a reference to the {@link EmbeddedDatabase} instance. * * @author Keith Donald * @author Juergen Hoeller @@ -62,9 +67,10 @@ public class EmbeddedDatabaseFactory { */ public static final String DEFAULT_DATABASE_NAME = "testdb"; - private static final Log logger = LogFactory.getLog(EmbeddedDatabaseFactory.class); + private boolean generateUniqueDatabaseName = false; + private String databaseName = DEFAULT_DATABASE_NAME; private DataSourceFactory dataSourceFactory = new SimpleDriverDataSourceFactory(); @@ -76,10 +82,25 @@ public class EmbeddedDatabaseFactory { private DataSource dataSource; + /** + * Set the {@code generateUniqueDatabaseName} flag to enable or disable + * generation of a pseudo-random unique ID to be used as the database name. + *
Setting this flag to {@code true} overrides any explicit name set + * via {@link #setDatabaseName}. + * @see #setDatabaseName + * @since 4.2 + */ + public void setGenerateUniqueDatabaseName(boolean generateUniqueDatabaseName) { + this.generateUniqueDatabaseName = generateUniqueDatabaseName; + } + /** * Set the name of the database. *
Defaults to {@value #DEFAULT_DATABASE_NAME}. + *
Will be overridden if the {@code generateUniqueDatabaseName} flag + * has been set to {@code true}. * @param databaseName name of the embedded database + * @see #setGenerateUniqueDatabaseName */ public void setDatabaseName(String databaseName) { Assert.hasText(databaseName, "Database name is required"); @@ -124,7 +145,7 @@ public class EmbeddedDatabaseFactory { } /** - * Factory method that returns the {@link EmbeddedDatabase embedded database} + * Factory method that returns the {@linkplain EmbeddedDatabase embedded database} * instance, which is also a {@link DataSource}. */ public EmbeddedDatabase getDatabase() { @@ -136,12 +157,20 @@ public class EmbeddedDatabaseFactory { /** - * Hook to initialize the embedded database. Subclasses may call this method - * to force initialization. + * Hook to initialize the embedded database. + *
If the {@code generateUniqueDatabaseName} flag has been set to {@code true}, + * the current value of the {@linkplain #setDatabaseName database name} will + * be overridden with an auto-generated name. + *
Subclasses may call this method to force initialization; however, + * this method should only be invoked once. *
After calling this method, {@link #getDataSource()} returns the
* {@link DataSource} providing connectivity to the database.
*/
protected void initDatabase() {
+ if (this.generateUniqueDatabaseName) {
+ setDatabaseName(UUID.randomUUID().toString());
+ }
+
// Create the embedded database source first
if (logger.isInfoEnabled()) {
logger.info("Creating embedded database '" + this.databaseName + "'");
diff --git a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.2.xsd b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.2.xsd
index c307361c686..c5f03511f4f 100644
--- a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.2.xsd
+++ b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.2.xsd
@@ -44,6 +44,17 @@
]]>
+