Commit d0494f52 authored by Phillip Webb's avatar Phillip Webb

Rework database auto-configure

Rework several aspects of database auto-configuration:

- Use RelaxedPropertyResolver to obtain property values
- Extract EmbeddedDatabaseConnection from EmbeddedDatabaseConfiguration
- Rename several configuration classes for consistency

Issue: #53028397
parent 3bbdc75f
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
package org.springframework.boot.autoconfigure.jdbc; package org.springframework.boot.autoconfigure.jdbc;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
...@@ -26,8 +26,8 @@ import org.springframework.util.StringUtils; ...@@ -26,8 +26,8 @@ import org.springframework.util.StringUtils;
* *
* @author Dave Syer * @author Dave Syer
*/ */
@ConfigurationProperties(path = "spring.data") @ConfigurationProperties(path = "spring.datasource")
public abstract class AbstractDataSourceConfiguration { public abstract class AbstractDataSourceConfiguration implements BeanClassLoaderAware {
private String driverClassName; private String driverClassName;
...@@ -49,19 +49,25 @@ public abstract class AbstractDataSourceConfiguration { ...@@ -49,19 +49,25 @@ public abstract class AbstractDataSourceConfiguration {
private boolean testOnReturn = false; private boolean testOnReturn = false;
private ClassLoader classLoader;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
protected String getDriverClassName() { protected String getDriverClassName() {
if (StringUtils.hasText(this.driverClassName)) { if (StringUtils.hasText(this.driverClassName)) {
return this.driverClassName; return this.driverClassName;
} }
EmbeddedDatabaseType embeddedDatabaseType = EmbeddedDatabaseConfiguration EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection
.getEmbeddedDatabaseType(); .get(this.classLoader);
this.driverClassName = EmbeddedDatabaseConfiguration this.driverClassName = embeddedDatabaseConnection.getDriverClassName();
.getEmbeddedDatabaseDriverClass(embeddedDatabaseType);
if (!StringUtils.hasText(this.driverClassName)) { if (!StringUtils.hasText(this.driverClassName)) {
throw new BeanCreationException( throw new BeanCreationException(
"Cannot determine embedded database driver class for database type " "Cannot determine embedded database driver class for database type "
+ embeddedDatabaseType + embeddedDatabaseConnection + ". If you want an embedded "
+ ". If you want an embedded database please put a supoprted one on the classpath."); + "database please put a supoprted one on the classpath.");
} }
return this.driverClassName; return this.driverClassName;
} }
...@@ -70,15 +76,14 @@ public abstract class AbstractDataSourceConfiguration { ...@@ -70,15 +76,14 @@ public abstract class AbstractDataSourceConfiguration {
if (StringUtils.hasText(this.url)) { if (StringUtils.hasText(this.url)) {
return this.url; return this.url;
} }
EmbeddedDatabaseType embeddedDatabaseType = EmbeddedDatabaseConfiguration EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection
.getEmbeddedDatabaseType(); .get(this.classLoader);
this.url = EmbeddedDatabaseConfiguration this.url = embeddedDatabaseConnection.getUrl();
.getEmbeddedDatabaseUrl(embeddedDatabaseType);
if (!StringUtils.hasText(this.url)) { if (!StringUtils.hasText(this.url)) {
throw new BeanCreationException( throw new BeanCreationException(
"Cannot determine embedded database url for database type " "Cannot determine embedded database url for database type "
+ embeddedDatabaseType + embeddedDatabaseConnection + ". If you want an embedded "
+ ". If you want an embedded database please put a supported on on the classpath."); + "database please put a supported on on the classpath.");
} }
return this.url; return this.url;
} }
......
...@@ -33,11 +33,12 @@ import org.springframework.dao.DataAccessResourceFailureException; ...@@ -33,11 +33,12 @@ import org.springframework.dao.DataAccessResourceFailureException;
* recommended in high volume environments (the Tomcat DataSource is more reliable). * recommended in high volume environments (the Tomcat DataSource is more reliable).
* *
* @author Dave Syer * @author Dave Syer
* @see DataSourceAutoConfiguration
*/ */
@Configuration @Configuration
public class BasicDataSourceConfiguration extends AbstractDataSourceConfiguration { public class CommonsDataSourceConfiguration extends AbstractDataSourceConfiguration {
private static Log logger = LogFactory.getLog(BasicDataSourceConfiguration.class); private static Log logger = LogFactory.getLog(CommonsDataSourceConfiguration.class);
private BasicDataSource pool; private BasicDataSource pool;
......
...@@ -26,13 +26,17 @@ import javax.sql.DataSource; ...@@ -26,13 +26,17 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.ConditionContext;
...@@ -61,7 +65,7 @@ import org.springframework.util.StringUtils; ...@@ -61,7 +65,7 @@ import org.springframework.util.StringUtils;
@Configuration @Configuration
@ConditionalOnClass(EmbeddedDatabaseType.class /* Spring JDBC */) @ConditionalOnClass(EmbeddedDatabaseType.class /* Spring JDBC */)
@ConditionalOnMissingBean(DataSource.class) @ConditionalOnMissingBean(DataSource.class)
public class DataSourceAutoConfiguration { public class DataSourceAutoConfiguration implements EnvironmentAware {
private static Log logger = LogFactory.getLog(DataSourceAutoConfiguration.class); private static Log logger = LogFactory.getLog(DataSourceAutoConfiguration.class);
...@@ -71,8 +75,66 @@ public class DataSourceAutoConfiguration { ...@@ -71,8 +75,66 @@ public class DataSourceAutoConfiguration {
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
private RelaxedPropertyResolver environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = new RelaxedPropertyResolver(environment, "spring.database.");
}
@PostConstruct
protected void initialize() throws Exception {
if (this.dataSource == null) {
logger.debug("No DataSource found so not initializing");
return;
}
String schema = this.environment.getProperty("schema");
if (schema == null) {
schema = "classpath*:schema-"
+ this.environment.getProperty("platform", "all") + ".sql";
}
List<Resource> resources = new ArrayList<Resource>();
for (String schemaLocation : StringUtils.commaDelimitedListToStringArray(schema)) {
resources.addAll(Arrays.asList(this.applicationContext
.getResources(schemaLocation)));
}
boolean exists = false;
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
for (Resource resource : resources) {
if (resource.exists()) {
exists = true;
populator.addScript(resource);
populator.setContinueOnError(true);
}
}
if (exists) {
DatabasePopulatorUtils.execute(populator, this.dataSource);
}
}
/**
* Determines if the {@code dataSource} being used by Spring was created from
* {@link EmbeddedDataSourceConfiguration}.
* @return true if the data source was auto-configured.
*/
public static boolean containsAutoConfiguredDataSource(
ConfigurableListableBeanFactory beanFactory) {
try {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dataSource");
return EmbeddedDataSourceConfiguration.class.getName().equals(
beanDefinition.getFactoryBeanName());
}
catch (NoSuchBeanDefinitionException ex) {
return false;
}
}
@Conditional(DataSourceAutoConfiguration.EmbeddedDatabaseCondition.class) @Conditional(DataSourceAutoConfiguration.EmbeddedDatabaseCondition.class)
@Import(EmbeddedDatabaseConfiguration.class) @Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedConfiguration { protected static class EmbeddedConfiguration {
} }
...@@ -82,7 +144,7 @@ public class DataSourceAutoConfiguration { ...@@ -82,7 +144,7 @@ public class DataSourceAutoConfiguration {
} }
@Conditional(DataSourceAutoConfiguration.BasicDatabaseCondition.class) @Conditional(DataSourceAutoConfiguration.BasicDatabaseCondition.class)
@Import(BasicDataSourceConfiguration.class) @Import(CommonsDataSourceConfiguration.class)
protected static class DbcpConfiguration { protected static class DbcpConfiguration {
} }
...@@ -107,35 +169,6 @@ public class DataSourceAutoConfiguration { ...@@ -107,35 +169,6 @@ public class DataSourceAutoConfiguration {
} }
@Value("${spring.database.schema:classpath*:schema-${spring.database.platform:all}.sql}")
private String schemaLocations = "";
@PostConstruct
protected void initialize() throws Exception {
if (this.dataSource == null) {
logger.debug("No DataSource found so not initializing");
return;
}
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
boolean exists = false;
List<Resource> resources = new ArrayList<Resource>();
for (String location : StringUtils
.commaDelimitedListToStringArray(this.schemaLocations)) {
resources
.addAll(Arrays.asList(this.applicationContext.getResources(location)));
}
for (Resource resource : resources) {
if (resource.exists()) {
exists = true;
populator.addScript(resource);
populator.setContinueOnError(true);
}
}
if (exists) {
DatabasePopulatorUtils.execute(populator, this.dataSource);
}
}
static abstract class NonEmbeddedDatabaseCondition extends SpringBootCondition { static abstract class NonEmbeddedDatabaseCondition extends SpringBootCondition {
protected abstract String getDataSourceClassName(); protected abstract String getDataSourceClassName();
...@@ -149,12 +182,13 @@ public class DataSourceAutoConfiguration { ...@@ -149,12 +182,13 @@ public class DataSourceAutoConfiguration {
+ " DataSource class not found"); + " DataSource class not found");
} }
String driverClassName = getDriverClassName(context.getEnvironment()); String driverClassName = getDriverClassName(context.getEnvironment(),
context.getClassLoader());
if (driverClassName == null) { if (driverClassName == null) {
return Outcome.noMatch("no database driver"); return Outcome.noMatch("no database driver");
} }
String url = getUrl(context.getEnvironment()); String url = getUrl(context.getEnvironment(), context.getClassLoader());
if (url == null) { if (url == null) {
return Outcome.noMatch("no database URL"); return Outcome.noMatch("no database URL");
} }
...@@ -166,24 +200,21 @@ public class DataSourceAutoConfiguration { ...@@ -166,24 +200,21 @@ public class DataSourceAutoConfiguration {
return Outcome.match("missing database driver " + driverClassName); return Outcome.match("missing database driver " + driverClassName);
} }
private String getDriverClassName(Environment environment) { private String getDriverClassName(Environment environment, ClassLoader classLoader) {
String driverClassName = environment == null ? null : environment String driverClassName = environment == null ? null : environment
.getProperty("spring.database.driverClassName"); .getProperty("spring.database.driverClassName");
if (driverClassName == null) { if (driverClassName == null) {
driverClassName = EmbeddedDatabaseConfiguration driverClassName = EmbeddedDatabaseConnection.get(classLoader)
.getEmbeddedDatabaseDriverClass(EmbeddedDatabaseConfiguration .getDriverClassName();
.getEmbeddedDatabaseType());
} }
return driverClassName; return driverClassName;
} }
private String getUrl(Environment environment) { private String getUrl(Environment environment, ClassLoader classLoader) {
String url = (environment == null ? null : environment String url = (environment == null ? null : environment
.getProperty("spring.database.url")); .getProperty("spring.database.url"));
if (url == null) { if (url == null) {
url = EmbeddedDatabaseConfiguration url = EmbeddedDatabaseConnection.get(classLoader).getUrl();
.getEmbeddedDatabaseUrl(EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseType());
} }
return url; return url;
} }
...@@ -229,8 +260,8 @@ public class DataSourceAutoConfiguration { ...@@ -229,8 +260,8 @@ public class DataSourceAutoConfiguration {
if (anyMatches(context, metadata, this.tomcatCondition, this.dbcpCondition)) { if (anyMatches(context, metadata, this.tomcatCondition, this.dbcpCondition)) {
return Outcome.noMatch("existing non-embedded database detected"); return Outcome.noMatch("existing non-embedded database detected");
} }
EmbeddedDatabaseType type = EmbeddedDatabaseConfiguration EmbeddedDatabaseType type = EmbeddedDatabaseConnection.get(
.getEmbeddedDatabaseType(); context.getClassLoader()).getType();
if (type == null) { if (type == null) {
return Outcome.noMatch("no embedded database detected"); return Outcome.noMatch("no embedded database detected");
} }
......
...@@ -16,52 +16,37 @@ ...@@ -16,52 +16,37 @@
package org.springframework.boot.autoconfigure.jdbc; package org.springframework.boot.autoconfigure.jdbc;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.util.ClassUtils;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for embedded databases. * Configuration for embedded data sources.
* *
* @author Phillip Webb * @author Phillip Webb
* @see DataSourceAutoConfiguration
*/ */
@Configuration @Configuration
public class EmbeddedDatabaseConfiguration { public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware {
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_DRIVER_CLASSES; private EmbeddedDatabase database;
static {
Map<EmbeddedDatabaseType, String> drivers = new LinkedHashMap<EmbeddedDatabaseType, String>();
drivers.put(EmbeddedDatabaseType.H2, "org.h2.Driver");
drivers.put(EmbeddedDatabaseType.DERBY, "org.apache.derby.jdbc.EmbeddedDriver");
drivers.put(EmbeddedDatabaseType.HSQL, "org.hsqldb.jdbcDriver");
EMBEDDED_DATABASE_DRIVER_CLASSES = drivers;
}
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_URLS; private ClassLoader classLoader;
static {
Map<EmbeddedDatabaseType, String> urls = new LinkedHashMap<EmbeddedDatabaseType, String>();
urls.put(EmbeddedDatabaseType.H2, "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1");
urls.put(EmbeddedDatabaseType.DERBY, "jdbc:derby:memory:testdb;create=true");
urls.put(EmbeddedDatabaseType.HSQL, "jdbc:hsqldb:mem:testdb");
EMBEDDED_DATABASE_URLS = urls;
}
private EmbeddedDatabase database; @Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Bean @Bean
public DataSource dataSource() { public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder() EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
.setType(getEmbeddedDatabaseType()); .setType(EmbeddedDatabaseConnection.get(this.classLoader).getType());
this.database = builder.build(); this.database = builder.build();
return this.database; return this.database;
} }
...@@ -73,24 +58,4 @@ public class EmbeddedDatabaseConfiguration { ...@@ -73,24 +58,4 @@ public class EmbeddedDatabaseConfiguration {
} }
} }
public static String getEmbeddedDatabaseDriverClass(
EmbeddedDatabaseType embeddedDatabaseType) {
return EMBEDDED_DATABASE_DRIVER_CLASSES.get(embeddedDatabaseType);
}
public static String getEmbeddedDatabaseUrl(EmbeddedDatabaseType embeddedDatabaseType) {
return EMBEDDED_DATABASE_URLS.get(embeddedDatabaseType);
}
public static EmbeddedDatabaseType getEmbeddedDatabaseType() {
for (Map.Entry<EmbeddedDatabaseType, String> entry : EMBEDDED_DATABASE_DRIVER_CLASSES
.entrySet()) {
if (ClassUtils.isPresent(entry.getValue(),
EmbeddedDatabaseConfiguration.class.getClassLoader())) {
return entry.getKey();
}
}
return null;
}
} }
/*
* Copyright 2012-2013 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.boot.autoconfigure.jdbc;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.util.ClassUtils;
/**
* Connection details for {@link EmbeddedDatabaseType embedded databases}.
*
* @author Phillip Webb
* @author Dave Syer
* @see #get(ClassLoader)
*/
public enum EmbeddedDatabaseConnection {
/**
* No Connection.
*/
NONE(null, null, null),
/**
* H2 Database Connection.
*/
H2(EmbeddedDatabaseType.H2, "org.h2.Driver", "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1"),
/**
* Derby Database Connection.
*/
DERBY(EmbeddedDatabaseType.DERBY, "org.apache.derby.jdbc.EmbeddedDriver",
"jdbc:derby:memory:testdb;create=true"),
/**
* HSQL Database Connection.
*/
HSQL(EmbeddedDatabaseType.HSQL, "org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:testdb");
private final EmbeddedDatabaseType type;
private final String driverClass;
private final String url;
private EmbeddedDatabaseConnection(EmbeddedDatabaseType type, String driverClass,
String url) {
this.type = type;
this.driverClass = driverClass;
this.url = url;
}
/**
* Returns the driver class name.
*/
public String getDriverClassName() {
return this.driverClass;
}
/**
* Returns the {@link EmbeddedDatabaseType} for the connection.
*/
public EmbeddedDatabaseType getType() {
return this.type;
}
/**
* Returns the URL for the connection.
*/
public String getUrl() {
return this.url;
}
/**
* Override for testing.
*/
static EmbeddedDatabaseConnection override;
/**
* Returns the most suitable {@link EmbeddedDatabaseConnection} for the given class
* loader.
* @param classLoader the class loader used to check for classes
* @return an {@link EmbeddedDatabaseConnection} or {@link #NONE}.
*/
public static EmbeddedDatabaseConnection get(ClassLoader classLoader) {
if (override != null) {
return override;
}
for (EmbeddedDatabaseConnection candidate : EmbeddedDatabaseConnection.values()) {
if (candidate != NONE
&& ClassUtils.isPresent(candidate.getDriverClassName(), classLoader)) {
return candidate;
}
}
return NONE;
}
}
...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Configuration; ...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Configuration;
* and tends not to deadlock in high volume environments. * and tends not to deadlock in high volume environments.
* *
* @author Dave Syer * @author Dave Syer
* @see DataSourceAutoConfiguration
*/ */
@Configuration @Configuration
public class TomcatDataSourceConfiguration extends AbstractDataSourceConfiguration { public class TomcatDataSourceConfiguration extends AbstractDataSourceConfiguration {
......
...@@ -16,23 +16,19 @@ ...@@ -16,23 +16,19 @@
package org.springframework.boot.autoconfigure.orm.jpa; package org.springframework.boot.autoconfigure.orm.jpa;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import org.hibernate.cfg.ImprovedNamingStrategy; import org.hibernate.cfg.ImprovedNamingStrategy;
import org.hibernate.ejb.HibernateEntityManager; import org.hibernate.ejb.HibernateEntityManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean; import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for Hibernate JPA. * {@link EnableAutoConfiguration Auto-configuration} for Hibernate JPA.
...@@ -44,56 +40,31 @@ import org.springframework.util.StringUtils; ...@@ -44,56 +40,31 @@ import org.springframework.util.StringUtils;
@EnableTransactionManagement @EnableTransactionManagement
public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration { public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_DIALECTS; private RelaxedPropertyResolver environment;
static {
EMBEDDED_DATABASE_DIALECTS = new LinkedHashMap<EmbeddedDatabaseType, String>();
EMBEDDED_DATABASE_DIALECTS.put(EmbeddedDatabaseType.HSQL,
"org.hibernate.dialect.HSQLDialect");
}
@Value("${spring.jpa.databasePlatform:${spring.jpa.database_platform:}}")
private String databasePlatform;
@Value("${spring.jpa.database:DEFAULT}")
private Database database = Database.DEFAULT;
@Value("${spring.jpa.showSql:${spring.jpa.show_sql:true}}") @Override
private boolean showSql; public void setEnvironment(Environment environment) {
super.setEnvironment(environment);
@Value("${spring.jpa.ddlAuto:${spring.jpa.ddl_auto:none}}") this.environment = new RelaxedPropertyResolver(environment,
private String ddlAuto; // e.g. none, validate, update, create, create-drop "spring.jpa.hibernate.");
}
@Value("${spring.jpa.hibernate.namingstrategy:org.hibernate.cfg.ImprovedNamingStrategy}")
private String namingStrategy;
@Bean
@Override @Override
public JpaVendorAdapter jpaVendorAdapter() { protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); return new HibernateJpaVendorAdapter();
adapter.setShowSql(this.showSql);
if (StringUtils.hasText(this.databasePlatform)) {
adapter.setDatabasePlatform(this.databasePlatform);
}
adapter.setDatabase(this.database);
return adapter;
} }
@Override @Override
protected void configure( protected void configure(
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) { LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
Map<String, Object> properties = entityManagerFactoryBean.getJpaPropertyMap(); Map<String, Object> properties = entityManagerFactoryBean.getJpaPropertyMap();
properties.put("hibernate.cache.provider_class", properties.put("hibernate.cache.provider_class", this.environment.getProperty(
"org.hibernate.cache.HashtableCacheProvider"); "cache-provider", "org.hibernate.cache.HashtableCacheProvider"));
if (StringUtils.hasLength(this.namingStrategy)) { properties.put("hibernate.ejb.naming_strategy", this.environment.getProperty(
properties.put("hibernate.ejb.naming_strategy", this.namingStrategy); "naming-strategy", ImprovedNamingStrategy.class.getName()));
} String ddlAuto = this.environment.getProperty("ddl-auto", "none");
else { if (!"none".equals(ddlAuto)) {
properties.put("hibernate.ejb.naming_strategy", properties.put("hibernate.hbm2ddl.auto", ddlAuto);
ImprovedNamingStrategy.class.getName());
}
if (StringUtils.hasLength(this.ddlAuto) && !"none".equals(this.ddlAuto)) {
properties.put("hibernate.hbm2ddl.auto", this.ddlAuto);
} }
} }
} }
...@@ -24,8 +24,6 @@ import javax.sql.DataSource; ...@@ -24,8 +24,6 @@ import javax.sql.DataSource;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigurationUtils; import org.springframework.boot.autoconfigure.AutoConfigurationUtils;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
...@@ -34,14 +32,18 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; ...@@ -34,14 +32,18 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConfiguration; import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter; import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.Assert; import org.springframework.util.Assert;
...@@ -57,10 +59,17 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter ...@@ -57,10 +59,17 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, @ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class,
EnableTransactionManagement.class, EntityManager.class }) EnableTransactionManagement.class, EntityManager.class })
@ConditionalOnBean(DataSource.class) @ConditionalOnBean(DataSource.class)
public abstract class JpaBaseConfiguration implements BeanFactoryAware { public abstract class JpaBaseConfiguration implements BeanFactoryAware, EnvironmentAware {
private ConfigurableListableBeanFactory beanFactory; private ConfigurableListableBeanFactory beanFactory;
private RelaxedPropertyResolver environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = new RelaxedPropertyResolver(environment, "spring.jpa.");
}
@Bean @Bean
public PlatformTransactionManager transactionManager() { public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory().getObject()); return new JpaTransactionManager(entityManagerFactory().getObject());
...@@ -72,29 +81,25 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { ...@@ -72,29 +81,25 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter()); entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactoryBean.setDataSource(getDataSource()); entityManagerFactoryBean.setDataSource(getDataSource());
entityManagerFactoryBean.setPackagesToScan(getPackagesToScan()); entityManagerFactoryBean.setPackagesToScan(getPackagesToScan());
entityManagerFactoryBean.getJpaPropertyMap().putAll(
this.environment.getSubProperties("properties."));
configure(entityManagerFactoryBean); configure(entityManagerFactoryBean);
return entityManagerFactoryBean; return entityManagerFactoryBean;
} }
/** @Bean
* Determines if the {@code dataSource} being used by Spring was created from public JpaVendorAdapter jpaVendorAdapter() {
* {@link EmbeddedDatabaseConfiguration}. AbstractJpaVendorAdapter adapter = createJpaVendorAdapter();
* @return true if the data source was auto-configured. adapter.setShowSql(this.environment.getProperty("show-sql", Boolean.class, true));
*/ adapter.setDatabasePlatform(this.environment.getProperty("database-platform"));
protected boolean isAutoConfiguredDataSource() { adapter.setDatabase(this.environment.getProperty("database", Database.class,
try { Database.DEFAULT));
BeanDefinition beanDefinition = this.beanFactory adapter.setGenerateDdl(this.environment.getProperty("generate-ddl",
.getBeanDefinition("dataSource"); Boolean.class, false));
return EmbeddedDatabaseConfiguration.class.getName().equals( return adapter;
beanDefinition.getFactoryBeanName());
}
catch (NoSuchBeanDefinitionException ex) {
return false;
}
} }
@Bean protected abstract AbstractJpaVendorAdapter createJpaVendorAdapter();
public abstract JpaVendorAdapter jpaVendorAdapter();
protected DataSource getDataSource() { protected DataSource getDataSource() {
try { try {
......
...@@ -21,10 +21,9 @@ import javax.persistence.EntityManagerFactory; ...@@ -21,10 +21,9 @@ import javax.persistence.EntityManagerFactory;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.ComponentScanDetectorConfiguration; import org.springframework.boot.autoconfigure.ComponentScanDetectorConfiguration;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.data.test.City; import org.springframework.boot.autoconfigure.data.test.City;
import org.springframework.boot.autoconfigure.data.test.CityRepository; import org.springframework.boot.autoconfigure.data.test.CityRepository;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
...@@ -35,7 +34,7 @@ import static org.junit.Assert.assertNotNull; ...@@ -35,7 +34,7 @@ import static org.junit.Assert.assertNotNull;
/** /**
* Tests for {@link JpaRepositoriesAutoConfiguration}. * Tests for {@link JpaRepositoriesAutoConfiguration}.
* *
* @author Dave Syer * @author Dave Syer
*/ */
public class JpaRepositoriesAutoConfigurationTests { public class JpaRepositoriesAutoConfigurationTests {
...@@ -47,7 +46,7 @@ public class JpaRepositoriesAutoConfigurationTests { ...@@ -47,7 +46,7 @@ public class JpaRepositoriesAutoConfigurationTests {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
this.context.register(TestConfiguration.class, this.context.register(TestConfiguration.class,
ComponentScanDetectorConfiguration.class, ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class, EmbeddedDataSourceConfiguration.class, HibernateJpaAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
......
...@@ -22,7 +22,7 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati ...@@ -22,7 +22,7 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati
import org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration; import org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.data.test.City; import org.springframework.boot.autoconfigure.data.test.City;
import org.springframework.boot.autoconfigure.data.test.CityRepository; import org.springframework.boot.autoconfigure.data.test.CityRepository;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -46,7 +46,7 @@ public class JpaWebAutoConfigurationTests { ...@@ -46,7 +46,7 @@ public class JpaWebAutoConfigurationTests {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext()); this.context.setServletContext(new MockServletContext());
this.context.register(TestConfiguration.class, this.context.register(TestConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class, EmbeddedDataSourceConfiguration.class, HibernateJpaAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
......
...@@ -19,23 +19,23 @@ package org.springframework.boot.autoconfigure.jdbc; ...@@ -19,23 +19,23 @@ package org.springframework.boot.autoconfigure.jdbc;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.jdbc.BasicDataSourceConfiguration; import org.springframework.boot.autoconfigure.jdbc.CommonsDataSourceConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
/** /**
* Tests for {@link BasicDataSourceConfiguration}. * Tests for {@link CommonsDataSourceConfiguration}.
* *
* @author Dave Syer * @author Dave Syer
*/ */
public class BasicDataSourceConfigurationTests { public class CommonsDataSourceConfigurationTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@Test @Test
public void testDataSourceExists() throws Exception { public void testDataSourceExists() throws Exception {
this.context.register(BasicDataSourceConfiguration.class); this.context.register(CommonsDataSourceConfiguration.class);
this.context.refresh(); this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class)); assertNotNull(this.context.getBean(DataSource.class));
this.context.close(); this.context.close();
......
...@@ -20,7 +20,7 @@ import javax.sql.DataSource; ...@@ -20,7 +20,7 @@ import javax.sql.DataSource;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.DataSourceTransactionManager;
...@@ -38,7 +38,7 @@ public class DataSourceTransactionManagerAutoConfigurationTests { ...@@ -38,7 +38,7 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
@Test @Test
public void testDataSourceExists() throws Exception { public void testDataSourceExists() throws Exception {
this.context.register(EmbeddedDatabaseConfiguration.class, this.context.register(EmbeddedDataSourceConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class); DataSourceTransactionManagerAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class)); assertNotNull(this.context.getBean(DataSource.class));
......
...@@ -19,24 +19,24 @@ package org.springframework.boot.autoconfigure.jdbc; ...@@ -19,24 +19,24 @@ package org.springframework.boot.autoconfigure.jdbc;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
/** /**
* Tests for {@link EmbeddedDatabaseConfiguration}. * Tests for {@link EmbeddedDataSourceConfiguration}.
* *
* @author Dave Syer * @author Dave Syer
*/ */
public class EmbeddedDatabaseConfigurationTests { public class EmbeddedDataSourceConfigurationTests {
private AnnotationConfigApplicationContext context; private AnnotationConfigApplicationContext context;
@Test @Test
public void testDefaultEmbeddedDatabase() throws Exception { public void testDefaultEmbeddedDatabase() throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
this.context.register(EmbeddedDatabaseConfiguration.class); this.context.register(EmbeddedDataSourceConfiguration.class);
this.context.refresh(); this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class)); assertNotNull(this.context.getBean(DataSource.class));
this.context.close(); this.context.close();
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
package org.springframework.boot.autoconfigure.jdbc; package org.springframework.boot.autoconfigure.jdbc;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource; import javax.sql.DataSource;
...@@ -26,8 +24,6 @@ import org.junit.After; ...@@ -26,8 +24,6 @@ import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConfiguration;
import org.springframework.boot.autoconfigure.jdbc.TomcatDataSourceConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
...@@ -42,15 +38,9 @@ public class TomcatDataSourceConfigurationTests { ...@@ -42,15 +38,9 @@ public class TomcatDataSourceConfigurationTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
private Map<Object, Object> old;
private Map<Object, Object> map;
@After @After
public void restore() { public void restore() {
if (this.map != null && this.old != null) { EmbeddedDatabaseConnection.override = null;
this.map.putAll(this.old);
}
} }
@Test @Test
...@@ -62,9 +52,7 @@ public class TomcatDataSourceConfigurationTests { ...@@ -62,9 +52,7 @@ public class TomcatDataSourceConfigurationTests {
@Test(expected = BeanCreationException.class) @Test(expected = BeanCreationException.class)
public void testBadUrl() throws Exception { public void testBadUrl() throws Exception {
this.map = getField(EmbeddedDatabaseConfiguration.class, "EMBEDDED_DATABASE_URLS"); EmbeddedDatabaseConnection.override = EmbeddedDatabaseConnection.NONE;
this.old = new HashMap<Object, Object>(this.map);
this.map.clear();
this.context.register(TomcatDataSourceConfiguration.class, this.context.register(TomcatDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
...@@ -73,10 +61,7 @@ public class TomcatDataSourceConfigurationTests { ...@@ -73,10 +61,7 @@ public class TomcatDataSourceConfigurationTests {
@Test(expected = BeanCreationException.class) @Test(expected = BeanCreationException.class)
public void testBadDriverClass() throws Exception { public void testBadDriverClass() throws Exception {
this.map = getField(EmbeddedDatabaseConfiguration.class, EmbeddedDatabaseConnection.override = EmbeddedDatabaseConnection.NONE;
"EMBEDDED_DATABASE_DRIVER_CLASSES");
this.old = new HashMap<Object, Object>(this.map);
this.map.clear();
this.context.register(TomcatDataSourceConfiguration.class, this.context.register(TomcatDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
......
/*
* Copyright 2012-2013 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.boot.autoconfigure.orm.jpa;
import java.util.Map;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.TestUtils;
import org.springframework.boot.autoconfigure.ComponentScanDetectorConfiguration;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.test.City;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Base for JPA tests and tests for {@link JpaBaseConfiguration}.
*
* @author Phillip Webb
* @author Dave Syer
*/
public abstract class AbstractJpaAutoConfigurationTests {
protected AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@After
public void close() {
this.context.close();
}
protected abstract Class<?> getAutoConfigureClass();
@Test
public void testEntityManagerCreated() throws Exception {
setupTestConfiguration();
this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class));
assertNotNull(this.context.getBean(JpaTransactionManager.class));
}
@Test
public void testDataSourceTransactionManagerNotCreated() throws Exception {
setupTestConfiguration();
this.context.register(DataSourceTransactionManagerAutoConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class));
assertTrue(this.context.getBean("transactionManager") instanceof JpaTransactionManager);
}
@Test
public void testOpenEntityManagerInViewInterceptorCreated() throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(TestConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
context.refresh();
assertNotNull(context.getBean(OpenEntityManagerInViewInterceptor.class));
context.close();
}
@Test
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenFilterPresent()
throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(TestFilterConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
context.refresh();
assertEquals(0, getInterceptorBeans(context).length);
context.close();
}
@Test
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenExplicitlyOff()
throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
TestUtils.addEnviroment(context, "spring.jpa.open_in_view:false");
context.register(TestConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
context.refresh();
assertEquals(0, getInterceptorBeans(context).length);
context.close();
}
@Test
public void customJpaProperties() throws Exception {
TestUtils.addEnviroment(this.context, "spring.jpa.properties.a:b",
"spring.jpa.properties.c:d");
setupTestConfiguration();
this.context.refresh();
LocalContainerEntityManagerFactoryBean bean = this.context
.getBean(LocalContainerEntityManagerFactoryBean.class);
Map<String, Object> map = bean.getJpaPropertyMap();
assertThat(map.get("a"), equalTo((Object) "b"));
assertThat(map.get("c"), equalTo((Object) "d"));
}
protected void setupTestConfiguration() {
this.context.register(TestConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
}
private String[] getInterceptorBeans(ApplicationContext context) {
return context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class);
}
@Configuration
@ComponentScan(basePackageClasses = { City.class })
protected static class TestConfiguration {
}
@Configuration
@ComponentScan(basePackageClasses = { City.class })
protected static class TestFilterConfiguration {
@Bean
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
return new OpenEntityManagerInViewFilter();
}
}
}
...@@ -16,121 +16,31 @@ ...@@ -16,121 +16,31 @@
package org.springframework.boot.autoconfigure.orm.jpa; package org.springframework.boot.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.TestUtils; import org.springframework.boot.TestUtils;
import org.springframework.boot.autoconfigure.ComponentScanDetectorConfiguration;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.test.City;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/** /**
* Tests for {@link HibernateJpaAutoConfiguration}. * Tests for {@link HibernateJpaAutoConfiguration}.
* *
* @author Dave Syer * @author Dave Syer
* @author Phillip Webb
*/ */
public class HibernateJpaAutoConfigurationTests { public class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTests {
private ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void testEntityManagerCreated() throws Exception {
((AnnotationConfigApplicationContext) this.context).register(
ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class));
assertNotNull(this.context.getBean(JpaTransactionManager.class));
}
@Test
public void testDataSourceTransactionManagerNotCreated() throws Exception {
((AnnotationConfigApplicationContext) this.context).register(
ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class));
assertTrue(this.context.getBean("transactionManager") instanceof JpaTransactionManager);
}
@Test
public void testOpenEntityManagerInViewInterceptorCreated() throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
this.context = context;
this.context.refresh();
assertNotNull(this.context.getBean(OpenEntityManagerInViewInterceptor.class));
}
@Test @Override
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenFilterPresent() protected Class<?> getAutoConfigureClass() {
throws Exception { return HibernateJpaAutoConfiguration.class;
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(TestFilterConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context = context;
this.context.refresh();
assertEquals(0, getInterceptorBeans().length);
}
@Test
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenExplicitlyOff()
throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
TestUtils.addEnviroment(context, "spring.jpa.open_in_view:false");
context.register(TestConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context = context;
this.context.refresh();
assertEquals(0, getInterceptorBeans().length);
} }
@Test @Test
public void testCustomNamingStrategy() throws Exception { public void testCustomNamingStrategy() throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); TestUtils.addEnviroment(this.context, "spring.jpa.hibernate.namingstrategy:"
TestUtils + "org.hibernate.cfg.EJB3NamingStrategy");
.addEnviroment(context, setupTestConfiguration();
"spring.jpa.hibernate.namingstrategy:org.hibernate.cfg.EJB3NamingStrategy");
context.register(TestConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context = context;
this.context.refresh(); this.context.refresh();
LocalContainerEntityManagerFactoryBean bean = this.context LocalContainerEntityManagerFactoryBean bean = this.context
.getBean(LocalContainerEntityManagerFactoryBean.class); .getBean(LocalContainerEntityManagerFactoryBean.class);
...@@ -139,21 +49,4 @@ public class HibernateJpaAutoConfigurationTests { ...@@ -139,21 +49,4 @@ public class HibernateJpaAutoConfigurationTests {
assertThat(actual, equalTo("org.hibernate.cfg.EJB3NamingStrategy")); assertThat(actual, equalTo("org.hibernate.cfg.EJB3NamingStrategy"));
} }
private String[] getInterceptorBeans() {
return this.context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class);
}
@ComponentScan(basePackageClasses = { City.class })
protected static class TestConfiguration {
}
@ComponentScan(basePackageClasses = { City.class })
@Configuration
protected static class TestFilterConfiguration {
@Bean
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
return new OpenEntityManagerInViewFilter();
}
}
} }
spring.jpa.ddl_auto: create-drop spring.jpa.hibernate.ddl-auto: create-drop
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment