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 @@
package org.springframework.boot.autoconfigure.jdbc;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.util.StringUtils;
/**
......@@ -26,8 +26,8 @@ import org.springframework.util.StringUtils;
*
* @author Dave Syer
*/
@ConfigurationProperties(path = "spring.data")
public abstract class AbstractDataSourceConfiguration {
@ConfigurationProperties(path = "spring.datasource")
public abstract class AbstractDataSourceConfiguration implements BeanClassLoaderAware {
private String driverClassName;
......@@ -49,19 +49,25 @@ public abstract class AbstractDataSourceConfiguration {
private boolean testOnReturn = false;
private ClassLoader classLoader;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
protected String getDriverClassName() {
if (StringUtils.hasText(this.driverClassName)) {
return this.driverClassName;
}
EmbeddedDatabaseType embeddedDatabaseType = EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseType();
this.driverClassName = EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseDriverClass(embeddedDatabaseType);
EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection
.get(this.classLoader);
this.driverClassName = embeddedDatabaseConnection.getDriverClassName();
if (!StringUtils.hasText(this.driverClassName)) {
throw new BeanCreationException(
"Cannot determine embedded database driver class for database type "
+ embeddedDatabaseType
+ ". If you want an embedded database please put a supoprted one on the classpath.");
+ embeddedDatabaseConnection + ". If you want an embedded "
+ "database please put a supoprted one on the classpath.");
}
return this.driverClassName;
}
......@@ -70,15 +76,14 @@ public abstract class AbstractDataSourceConfiguration {
if (StringUtils.hasText(this.url)) {
return this.url;
}
EmbeddedDatabaseType embeddedDatabaseType = EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseType();
this.url = EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseUrl(embeddedDatabaseType);
EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection
.get(this.classLoader);
this.url = embeddedDatabaseConnection.getUrl();
if (!StringUtils.hasText(this.url)) {
throw new BeanCreationException(
"Cannot determine embedded database url for database type "
+ embeddedDatabaseType
+ ". If you want an embedded database please put a supported on on the classpath.");
+ embeddedDatabaseConnection + ". If you want an embedded "
+ "database please put a supported on on the classpath.");
}
return this.url;
}
......
......@@ -33,11 +33,12 @@ import org.springframework.dao.DataAccessResourceFailureException;
* recommended in high volume environments (the Tomcat DataSource is more reliable).
*
* @author Dave Syer
* @see DataSourceAutoConfiguration
*/
@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;
......
......@@ -26,13 +26,17 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.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.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.ApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
......@@ -61,7 +65,7 @@ import org.springframework.util.StringUtils;
@Configuration
@ConditionalOnClass(EmbeddedDatabaseType.class /* Spring JDBC */)
@ConditionalOnMissingBean(DataSource.class)
public class DataSourceAutoConfiguration {
public class DataSourceAutoConfiguration implements EnvironmentAware {
private static Log logger = LogFactory.getLog(DataSourceAutoConfiguration.class);
......@@ -71,8 +75,66 @@ public class DataSourceAutoConfiguration {
@Autowired
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)
@Import(EmbeddedDatabaseConfiguration.class)
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedConfiguration {
}
......@@ -82,7 +144,7 @@ public class DataSourceAutoConfiguration {
}
@Conditional(DataSourceAutoConfiguration.BasicDatabaseCondition.class)
@Import(BasicDataSourceConfiguration.class)
@Import(CommonsDataSourceConfiguration.class)
protected static class DbcpConfiguration {
}
......@@ -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 {
protected abstract String getDataSourceClassName();
......@@ -149,12 +182,13 @@ public class DataSourceAutoConfiguration {
+ " DataSource class not found");
}
String driverClassName = getDriverClassName(context.getEnvironment());
String driverClassName = getDriverClassName(context.getEnvironment(),
context.getClassLoader());
if (driverClassName == null) {
return Outcome.noMatch("no database driver");
}
String url = getUrl(context.getEnvironment());
String url = getUrl(context.getEnvironment(), context.getClassLoader());
if (url == null) {
return Outcome.noMatch("no database URL");
}
......@@ -166,24 +200,21 @@ public class DataSourceAutoConfiguration {
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
.getProperty("spring.database.driverClassName");
if (driverClassName == null) {
driverClassName = EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseDriverClass(EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseType());
driverClassName = EmbeddedDatabaseConnection.get(classLoader)
.getDriverClassName();
}
return driverClassName;
}
private String getUrl(Environment environment) {
private String getUrl(Environment environment, ClassLoader classLoader) {
String url = (environment == null ? null : environment
.getProperty("spring.database.url"));
if (url == null) {
url = EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseUrl(EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseType());
url = EmbeddedDatabaseConnection.get(classLoader).getUrl();
}
return url;
}
......@@ -229,8 +260,8 @@ public class DataSourceAutoConfiguration {
if (anyMatches(context, metadata, this.tomcatCondition, this.dbcpCondition)) {
return Outcome.noMatch("existing non-embedded database detected");
}
EmbeddedDatabaseType type = EmbeddedDatabaseConfiguration
.getEmbeddedDatabaseType();
EmbeddedDatabaseType type = EmbeddedDatabaseConnection.get(
context.getClassLoader()).getType();
if (type == null) {
return Outcome.noMatch("no embedded database detected");
}
......
......@@ -16,52 +16,37 @@
package org.springframework.boot.autoconfigure.jdbc;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.PreDestroy;
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.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
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
* @see DataSourceAutoConfiguration
*/
@Configuration
public class EmbeddedDatabaseConfiguration {
public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware {
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_DRIVER_CLASSES;
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 EmbeddedDatabase database;
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_URLS;
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 ClassLoader classLoader;
private EmbeddedDatabase database;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
.setType(getEmbeddedDatabaseType());
.setType(EmbeddedDatabaseConnection.get(this.classLoader).getType());
this.database = builder.build();
return this.database;
}
......@@ -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;
* and tends not to deadlock in high volume environments.
*
* @author Dave Syer
* @see DataSourceAutoConfiguration
*/
@Configuration
public class TomcatDataSourceConfiguration extends AbstractDataSourceConfiguration {
......
......@@ -16,23 +16,19 @@
package org.springframework.boot.autoconfigure.orm.jpa;
import java.util.LinkedHashMap;
import java.util.Map;
import org.hibernate.cfg.ImprovedNamingStrategy;
import org.hibernate.ejb.HibernateEntityManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
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.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.core.env.Environment;
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.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Hibernate JPA.
......@@ -44,56 +40,31 @@ import org.springframework.util.StringUtils;
@EnableTransactionManagement
public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_DIALECTS;
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}}")
private boolean showSql;
@Value("${spring.jpa.ddlAuto:${spring.jpa.ddl_auto:none}}")
private String ddlAuto; // e.g. none, validate, update, create, create-drop
@Value("${spring.jpa.hibernate.namingstrategy:org.hibernate.cfg.ImprovedNamingStrategy}")
private String namingStrategy;
private RelaxedPropertyResolver environment;
@Bean
@Override
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(this.showSql);
if (StringUtils.hasText(this.databasePlatform)) {
adapter.setDatabasePlatform(this.databasePlatform);
public void setEnvironment(Environment environment) {
super.setEnvironment(environment);
this.environment = new RelaxedPropertyResolver(environment,
"spring.jpa.hibernate.");
}
adapter.setDatabase(this.database);
return adapter;
@Override
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
@Override
protected void configure(
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
Map<String, Object> properties = entityManagerFactoryBean.getJpaPropertyMap();
properties.put("hibernate.cache.provider_class",
"org.hibernate.cache.HashtableCacheProvider");
if (StringUtils.hasLength(this.namingStrategy)) {
properties.put("hibernate.ejb.naming_strategy", this.namingStrategy);
}
else {
properties.put("hibernate.ejb.naming_strategy",
ImprovedNamingStrategy.class.getName());
properties.put("hibernate.cache.provider_class", this.environment.getProperty(
"cache-provider", "org.hibernate.cache.HashtableCacheProvider"));
properties.put("hibernate.ejb.naming_strategy", this.environment.getProperty(
"naming-strategy", ImprovedNamingStrategy.class.getName()));
String ddlAuto = this.environment.getProperty("ddl-auto", "none");
if (!"none".equals(ddlAuto)) {
properties.put("hibernate.hbm2ddl.auto", ddlAuto);
}
if (StringUtils.hasLength(this.ddlAuto) && !"none".equals(this.ddlAuto)) {
properties.put("hibernate.hbm2ddl.auto", this.ddlAuto);
}
}
}
......@@ -24,8 +24,6 @@ import javax.sql.DataSource;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
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.boot.autoconfigure.AutoConfigurationUtils;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
......@@ -34,14 +32,18 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
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.annotation.EnableTransactionManagement;
import org.springframework.util.Assert;
......@@ -57,10 +59,17 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class,
EnableTransactionManagement.class, EntityManager.class })
@ConditionalOnBean(DataSource.class)
public abstract class JpaBaseConfiguration implements BeanFactoryAware {
public abstract class JpaBaseConfiguration implements BeanFactoryAware, EnvironmentAware {
private ConfigurableListableBeanFactory beanFactory;
private RelaxedPropertyResolver environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = new RelaxedPropertyResolver(environment, "spring.jpa.");
}
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory().getObject());
......@@ -72,29 +81,25 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactoryBean.setDataSource(getDataSource());
entityManagerFactoryBean.setPackagesToScan(getPackagesToScan());
entityManagerFactoryBean.getJpaPropertyMap().putAll(
this.environment.getSubProperties("properties."));
configure(entityManagerFactoryBean);
return entityManagerFactoryBean;
}
/**
* Determines if the {@code dataSource} being used by Spring was created from
* {@link EmbeddedDatabaseConfiguration}.
* @return true if the data source was auto-configured.
*/
protected boolean isAutoConfiguredDataSource() {
try {
BeanDefinition beanDefinition = this.beanFactory
.getBeanDefinition("dataSource");
return EmbeddedDatabaseConfiguration.class.getName().equals(
beanDefinition.getFactoryBeanName());
}
catch (NoSuchBeanDefinitionException ex) {
return false;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
AbstractJpaVendorAdapter adapter = createJpaVendorAdapter();
adapter.setShowSql(this.environment.getProperty("show-sql", Boolean.class, true));
adapter.setDatabasePlatform(this.environment.getProperty("database-platform"));
adapter.setDatabase(this.environment.getProperty("database", Database.class,
Database.DEFAULT));
adapter.setGenerateDdl(this.environment.getProperty("generate-ddl",
Boolean.class, false));
return adapter;
}
@Bean
public abstract JpaVendorAdapter jpaVendorAdapter();
protected abstract AbstractJpaVendorAdapter createJpaVendorAdapter();
protected DataSource getDataSource() {
try {
......
......@@ -21,10 +21,9 @@ import javax.persistence.EntityManagerFactory;
import org.junit.Test;
import org.springframework.boot.autoconfigure.ComponentScanDetectorConfiguration;
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.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.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
......@@ -47,7 +46,7 @@ public class JpaRepositoriesAutoConfigurationTests {
this.context = new AnnotationConfigApplicationContext();
this.context.register(TestConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
EmbeddedDataSourceConfiguration.class, HibernateJpaAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
......
......@@ -22,7 +22,7 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati
import org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.data.test.City;
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.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
......@@ -46,7 +46,7 @@ public class JpaWebAutoConfigurationTests {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(TestConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
EmbeddedDataSourceConfiguration.class, HibernateJpaAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
......
......@@ -19,23 +19,23 @@ package org.springframework.boot.autoconfigure.jdbc;
import javax.sql.DataSource;
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 static org.junit.Assert.assertNotNull;
/**
* Tests for {@link BasicDataSourceConfiguration}.
* Tests for {@link CommonsDataSourceConfiguration}.
*
* @author Dave Syer
*/
public class BasicDataSourceConfigurationTests {
public class CommonsDataSourceConfigurationTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@Test
public void testDataSourceExists() throws Exception {
this.context.register(BasicDataSourceConfiguration.class);
this.context.register(CommonsDataSourceConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class));
this.context.close();
......
......@@ -20,7 +20,7 @@ import javax.sql.DataSource;
import org.junit.Test;
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.jdbc.datasource.DataSourceTransactionManager;
......@@ -38,7 +38,7 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
@Test
public void testDataSourceExists() throws Exception {
this.context.register(EmbeddedDatabaseConfiguration.class,
this.context.register(EmbeddedDataSourceConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class));
......
......@@ -19,24 +19,24 @@ package org.springframework.boot.autoconfigure.jdbc;
import javax.sql.DataSource;
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 static org.junit.Assert.assertNotNull;
/**
* Tests for {@link EmbeddedDatabaseConfiguration}.
* Tests for {@link EmbeddedDataSourceConfiguration}.
*
* @author Dave Syer
*/
public class EmbeddedDatabaseConfigurationTests {
public class EmbeddedDataSourceConfigurationTests {
private AnnotationConfigApplicationContext context;
@Test
public void testDefaultEmbeddedDatabase() throws Exception {
this.context = new AnnotationConfigApplicationContext();
this.context.register(EmbeddedDatabaseConfiguration.class);
this.context.register(EmbeddedDataSourceConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(DataSource.class));
this.context.close();
......
......@@ -17,8 +17,6 @@
package org.springframework.boot.autoconfigure.jdbc;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
......@@ -26,8 +24,6 @@ import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
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.util.ReflectionUtils;
......@@ -42,15 +38,9 @@ public class TomcatDataSourceConfigurationTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
private Map<Object, Object> old;
private Map<Object, Object> map;
@After
public void restore() {
if (this.map != null && this.old != null) {
this.map.putAll(this.old);
}
EmbeddedDatabaseConnection.override = null;
}
@Test
......@@ -62,9 +52,7 @@ public class TomcatDataSourceConfigurationTests {
@Test(expected = BeanCreationException.class)
public void testBadUrl() throws Exception {
this.map = getField(EmbeddedDatabaseConfiguration.class, "EMBEDDED_DATABASE_URLS");
this.old = new HashMap<Object, Object>(this.map);
this.map.clear();
EmbeddedDatabaseConnection.override = EmbeddedDatabaseConnection.NONE;
this.context.register(TomcatDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
......@@ -73,10 +61,7 @@ public class TomcatDataSourceConfigurationTests {
@Test(expected = BeanCreationException.class)
public void testBadDriverClass() throws Exception {
this.map = getField(EmbeddedDatabaseConfiguration.class,
"EMBEDDED_DATABASE_DRIVER_CLASSES");
this.old = new HashMap<Object, Object>(this.map);
this.map.clear();
EmbeddedDatabaseConnection.override = EmbeddedDatabaseConnection.NONE;
this.context.register(TomcatDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
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 @@
package org.springframework.boot.autoconfigure.orm.jpa;
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.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.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;
/**
* Tests for {@link HibernateJpaAutoConfiguration}.
*
* @author Dave Syer
* @author Phillip Webb
*/
public class HibernateJpaAutoConfigurationTests {
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
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenFilterPresent()
throws Exception {
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);
}
public class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTests {
@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);
@Override
protected Class<?> getAutoConfigureClass() {
return HibernateJpaAutoConfiguration.class;
}
@Test
public void testCustomNamingStrategy() throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
TestUtils
.addEnviroment(context,
"spring.jpa.hibernate.namingstrategy:org.hibernate.cfg.EJB3NamingStrategy");
context.register(TestConfiguration.class,
ComponentScanDetectorConfiguration.class,
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context = context;
TestUtils.addEnviroment(this.context, "spring.jpa.hibernate.namingstrategy:"
+ "org.hibernate.cfg.EJB3NamingStrategy");
setupTestConfiguration();
this.context.refresh();
LocalContainerEntityManagerFactoryBean bean = this.context
.getBean(LocalContainerEntityManagerFactoryBean.class);
......@@ -139,21 +49,4 @@ public class HibernateJpaAutoConfigurationTests {
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
\ No newline at end of file
spring.jpa.hibernate.ddl-auto: create-drop
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