Default Hibernate DDL auto to none with Flyway/Liquibase
This commit adds a strategy interface to specific if a given DataSource has its schema managed. The Hibernate auto-configuration uses it to set it to "none" if a mechanism to initialize the DataSource is found and "create-drop" otherwise. Both Flyway and Liquibase implements that strategy interface and register it in the context accordingly. Closes gh-9262
This commit is contained in:
parent
8babd5d4c5
commit
afda0ec129
|
@ -80,6 +80,13 @@ public class FlywayAutoConfiguration {
|
|||
return new StringOrNumberToMigrationVersionConverter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlywaySchemaManagementProvider flywayDefaultDdlModeProvider(
|
||||
ObjectProvider<List<Flyway>> flyways) {
|
||||
return new FlywaySchemaManagementProvider(
|
||||
flyways.getIfAvailable(Collections::emptyList));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(Flyway.class)
|
||||
@EnableConfigurationProperties(FlywayProperties.class)
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.flyway;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
|
||||
import org.springframework.boot.jdbc.SchemaManagement;
|
||||
import org.springframework.boot.jdbc.SchemaManagementProvider;
|
||||
|
||||
/**
|
||||
* A Flyway {@link SchemaManagementProvider} that determines if the schema is managed by
|
||||
* looking at available {@link Flyway} instances.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class FlywaySchemaManagementProvider implements SchemaManagementProvider {
|
||||
|
||||
private final List<Flyway> flyways;
|
||||
|
||||
FlywaySchemaManagementProvider(List<Flyway> flyways) {
|
||||
this.flyways = flyways;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaManagement getSchemaManagement(DataSource dataSource) {
|
||||
for (Flyway flyway : this.flyways) {
|
||||
if (dataSource.equals(flyway.getDataSource())) {
|
||||
return SchemaManagement.MANAGED;
|
||||
}
|
||||
}
|
||||
return SchemaManagement.UNMANAGED;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,8 @@
|
|||
package org.springframework.boot.autoconfigure.liquibase;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
@ -65,6 +67,13 @@ import org.springframework.util.ReflectionUtils;
|
|||
HibernateJpaAutoConfiguration.class })
|
||||
public class LiquibaseAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public LiquibaseSchemaManagementProvider liquibaseDefaultDdlModeProvider(
|
||||
ObjectProvider<List<SpringLiquibase>> liquibases) {
|
||||
return new LiquibaseSchemaManagementProvider(
|
||||
liquibases.getIfAvailable(Collections::emptyList));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(SpringLiquibase.class)
|
||||
@EnableConfigurationProperties(LiquibaseProperties.class)
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.liquibase;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
|
||||
import org.springframework.boot.jdbc.SchemaManagement;
|
||||
import org.springframework.boot.jdbc.SchemaManagementProvider;
|
||||
|
||||
/**
|
||||
* A Liquibase {@link SchemaManagementProvider} that determines if the schema is managed
|
||||
* by looking at available {@link SpringLiquibase} instances.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class LiquibaseSchemaManagementProvider implements SchemaManagementProvider {
|
||||
|
||||
private final List<SpringLiquibase> liquibases;
|
||||
|
||||
LiquibaseSchemaManagementProvider(List<SpringLiquibase> liquibases) {
|
||||
this.liquibases = liquibases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaManagement getSchemaManagement(DataSource dataSource) {
|
||||
for (SpringLiquibase liquibase : this.liquibases) {
|
||||
if (dataSource.equals(liquibase.getDataSource())) {
|
||||
return SchemaManagement.MANAGED;
|
||||
}
|
||||
}
|
||||
return SchemaManagement.UNMANAGED;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
|||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceInitializedEvent;
|
||||
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
@ -89,8 +90,10 @@ class DataSourceInitializedPublisher implements BeanPostProcessor {
|
|||
if (this.properties == null) {
|
||||
return true; // better safe than sorry
|
||||
}
|
||||
Map<String, String> hibernate = this.properties
|
||||
.getHibernateProperties(dataSource);
|
||||
String defaultDdlAuto = (EmbeddedDatabaseConnection.isEmbedded(dataSource)
|
||||
? "create-drop" : "none");
|
||||
Map<String, String> hibernate = this.properties.getHibernateProperties(
|
||||
defaultDdlAuto);
|
||||
if (hibernate.containsKey("hibernate.hbm2ddl.auto")) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.boot.jdbc.SchemaManagement;
|
||||
import org.springframework.boot.jdbc.SchemaManagementProvider;
|
||||
|
||||
/**
|
||||
* A {@link SchemaManagementProvider} that invokes a configurable number of
|
||||
* {@link SchemaManagementProvider} instances for embedded data sources only.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class HibernateDefaultDdlAutoProvider implements SchemaManagementProvider {
|
||||
|
||||
private final List<SchemaManagementProvider> providers;
|
||||
|
||||
HibernateDefaultDdlAutoProvider(List<SchemaManagementProvider> providers) {
|
||||
this.providers = providers;
|
||||
}
|
||||
|
||||
public String getDefaultDdlAuto(DataSource dataSource) {
|
||||
if (!EmbeddedDatabaseConnection.isEmbedded(dataSource)) {
|
||||
return "none";
|
||||
}
|
||||
SchemaManagement schemaManagement = getSchemaManagement(dataSource);
|
||||
if (SchemaManagement.MANAGED.equals(schemaManagement)) {
|
||||
return "none";
|
||||
}
|
||||
return "create-drop";
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaManagement getSchemaManagement(DataSource dataSource) {
|
||||
for (SchemaManagementProvider provider : this.providers) {
|
||||
SchemaManagement schemaManagement = provider.getSchemaManagement(dataSource);
|
||||
if (SchemaManagement.MANAGED.equals(schemaManagement)) {
|
||||
return schemaManagement;
|
||||
}
|
||||
}
|
||||
return SchemaManagement.UNMANAGED;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,7 +17,9 @@
|
|||
package org.springframework.boot.autoconfigure.orm.jpa;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
@ -37,6 +39,7 @@ import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
|||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.HibernateEntityManagerCondition;
|
||||
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
|
||||
import org.springframework.boot.jdbc.SchemaManagementProvider;
|
||||
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
|
@ -85,12 +88,17 @@ public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
|
|||
"org.hibernate.engine.transaction.jta.platform.internal.WebSphereExtendedJtaPlatform",
|
||||
"org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform", };
|
||||
|
||||
private final HibernateDefaultDdlAutoProvider defaultDdlAutoProvider;
|
||||
|
||||
public HibernateJpaAutoConfiguration(DataSource dataSource,
|
||||
JpaProperties jpaProperties,
|
||||
ObjectProvider<JtaTransactionManager> jtaTransactionManager,
|
||||
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
|
||||
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers,
|
||||
ObjectProvider<List<SchemaManagementProvider>> providers) {
|
||||
super(dataSource, jpaProperties, jtaTransactionManager,
|
||||
transactionManagerCustomizers);
|
||||
this.defaultDdlAutoProvider = new HibernateDefaultDdlAutoProvider(
|
||||
providers.getIfAvailable(Collections::emptyList));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,7 +109,9 @@ public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
|
|||
@Override
|
||||
protected Map<String, Object> getVendorProperties() {
|
||||
Map<String, Object> vendorProperties = new LinkedHashMap<>();
|
||||
vendorProperties.putAll(getProperties().getHibernateProperties(getDataSource()));
|
||||
String defaultDdlMode = this.defaultDdlAutoProvider.getDefaultDdlAuto(
|
||||
getDataSource());
|
||||
vendorProperties.putAll(getProperties().getHibernateProperties(defaultDdlMode));
|
||||
return vendorProperties;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.util.Map;
|
|||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
@ -119,11 +118,11 @@ public class JpaProperties {
|
|||
/**
|
||||
* Get configuration properties for the initialization of the main Hibernate
|
||||
* EntityManagerFactory.
|
||||
* @param dataSource the DataSource in case it is needed to determine the properties
|
||||
* @param defaultDdlAuto the default DDL auto (can be {@code null})
|
||||
* @return some Hibernate properties for configuration
|
||||
*/
|
||||
public Map<String, String> getHibernateProperties(DataSource dataSource) {
|
||||
return this.hibernate.getAdditionalProperties(this.properties, dataSource);
|
||||
public Map<String, String> getHibernateProperties(String defaultDdlAuto) {
|
||||
return this.hibernate.getAdditionalProperties(this.properties, defaultDdlAuto);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,8 +145,8 @@ public class JpaProperties {
|
|||
|
||||
/**
|
||||
* DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto"
|
||||
* property. Default to "create-drop" when using an embedded database, "none"
|
||||
* otherwise.
|
||||
* property. Default to "create-drop" when using an embedded database and no
|
||||
* schema manager was detected, "none" otherwise.
|
||||
*/
|
||||
private String ddlAuto;
|
||||
|
||||
|
@ -181,11 +180,11 @@ public class JpaProperties {
|
|||
}
|
||||
|
||||
private Map<String, String> getAdditionalProperties(Map<String, String> existing,
|
||||
DataSource dataSource) {
|
||||
String defaultDdlAuto) {
|
||||
Map<String, String> result = new HashMap<>(existing);
|
||||
applyNewIdGeneratorMappings(result);
|
||||
getNaming().applyNamingStrategies(result);
|
||||
String ddlAuto = getOrDeduceDdlAuto(existing, dataSource);
|
||||
String ddlAuto = determineDdlAuto(existing, defaultDdlAuto);
|
||||
if (StringUtils.hasText(ddlAuto) && !"none".equals(ddlAuto)) {
|
||||
result.put("hibernate.hbm2ddl.auto", ddlAuto);
|
||||
}
|
||||
|
@ -205,10 +204,9 @@ public class JpaProperties {
|
|||
}
|
||||
}
|
||||
|
||||
private String getOrDeduceDdlAuto(Map<String, String> existing,
|
||||
DataSource dataSource) {
|
||||
String ddlAuto = (this.ddlAuto != null ? this.ddlAuto
|
||||
: getDefaultDdlAuto(dataSource));
|
||||
private String determineDdlAuto(Map<String, String> existing,
|
||||
String defaultDdlAuto) {
|
||||
String ddlAuto = (this.ddlAuto != null ? this.ddlAuto : defaultDdlAuto);
|
||||
if (!existing.containsKey("hibernate." + "hbm2ddl.auto")
|
||||
&& !"none".equals(ddlAuto)) {
|
||||
return ddlAuto;
|
||||
|
@ -219,13 +217,6 @@ public class JpaProperties {
|
|||
return "none";
|
||||
}
|
||||
|
||||
private String getDefaultDdlAuto(DataSource dataSource) {
|
||||
if (EmbeddedDatabaseConnection.isEmbedded(dataSource)) {
|
||||
return "create-drop";
|
||||
}
|
||||
return "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Naming {
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
|||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||
import org.springframework.boot.jdbc.SchemaManagement;
|
||||
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
@ -114,6 +115,19 @@ public class FlywayAutoConfigurationTests {
|
|||
.isEqualTo(this.context.getBean("flywayDataSource"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void schemaManagementProviderDetectsDataSource() throws Exception {
|
||||
registerAndRefresh(FlywayDataSourceConfiguration.class,
|
||||
EmbeddedDataSourceConfiguration.class, FlywayAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
FlywaySchemaManagementProvider schemaManagementProvider = this.context.getBean(
|
||||
FlywaySchemaManagementProvider.class);
|
||||
assertThat(schemaManagementProvider.getSchemaManagement(this.context.getBean(
|
||||
DataSource.class))).isEqualTo(SchemaManagement.UNMANAGED);
|
||||
assertThat(schemaManagementProvider.getSchemaManagement(this.context.getBean(
|
||||
"flywayDataSource", DataSource.class))).isEqualTo(SchemaManagement.MANAGED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultFlyway() throws Exception {
|
||||
registerAndRefresh(EmbeddedDataSourceConfiguration.class,
|
||||
|
|
|
@ -59,44 +59,6 @@ public class CustomHibernateJpaAutoConfigurationTests {
|
|||
this.context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultDdlAutoForMySql() throws Exception {
|
||||
// Set up environment so we get a MySQL database but don't require server to be
|
||||
// running...
|
||||
TestPropertyValues
|
||||
.of("spring.datasource.type:"
|
||||
+ org.apache.tomcat.jdbc.pool.DataSource.class.getName(),
|
||||
"spring.datasource.database:mysql",
|
||||
"spring.datasource.url:jdbc:mysql://localhost/nonexistent",
|
||||
"spring.datasource.initialize:false", "spring.jpa.database:MYSQL")
|
||||
.applyTo(this.context);
|
||||
this.context.register(TestConfiguration.class, DataSourceAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
JpaProperties bean = this.context.getBean(JpaProperties.class);
|
||||
DataSource dataSource = this.context.getBean(DataSource.class);
|
||||
String actual = bean.getHibernateProperties(dataSource)
|
||||
.get("hibernate.hbm2ddl.auto");
|
||||
// Default is generic and safe
|
||||
assertThat(actual).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultDdlAutoForEmbedded() throws Exception {
|
||||
TestPropertyValues.of("spring.datasource.initialize:false").applyTo(this.context);
|
||||
this.context.register(TestConfiguration.class,
|
||||
EmbeddedDataSourceConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
JpaProperties bean = this.context.getBean(JpaProperties.class);
|
||||
DataSource dataSource = this.context.getBean(DataSource.class);
|
||||
String actual = bean.getHibernateProperties(dataSource)
|
||||
.get("hibernate.hbm2ddl.auto");
|
||||
assertThat(actual).isEqualTo("create-drop");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamingStrategyDelegatorTakesPrecedence() {
|
||||
TestPropertyValues
|
||||
|
@ -108,8 +70,7 @@ public class CustomHibernateJpaAutoConfigurationTests {
|
|||
HibernateJpaAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
JpaProperties bean = this.context.getBean(JpaProperties.class);
|
||||
DataSource dataSource = this.context.getBean(DataSource.class);
|
||||
Map<String, String> hibernateProperties = bean.getHibernateProperties(dataSource);
|
||||
Map<String, String> hibernateProperties = bean.getHibernateProperties("create-drop");
|
||||
assertThat(hibernateProperties.get("hibernate.ejb.naming_strategy")).isNull();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.Collections;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.jdbc.SchemaManagement;
|
||||
import org.springframework.boot.jdbc.SchemaManagementProvider;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link HibernateDefaultDdlAutoProvider}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class HibernateDefaultDdlAutoProviderTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class))
|
||||
.withPropertyValues("spring.datasource.initialize:false");
|
||||
|
||||
@Test
|
||||
public void defaultDdlAutoForMysql() {
|
||||
// Set up environment so we get a MySQL database but don't require server to be
|
||||
// running...
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.datasource.type:"
|
||||
+ org.apache.tomcat.jdbc.pool.DataSource.class.getName(),
|
||||
"spring.datasource.database:mysql",
|
||||
"spring.datasource.url:jdbc:mysql://localhost/nonexistent",
|
||||
"spring.jpa.database:MYSQL"
|
||||
).run((context) -> {
|
||||
HibernateDefaultDdlAutoProvider ddlAutoProvider = new HibernateDefaultDdlAutoProvider(
|
||||
Collections.emptyList());
|
||||
assertThat(ddlAutoProvider.getDefaultDdlAuto(
|
||||
context.getBean(DataSource.class))).isEqualTo("none");
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultDDlAutoForEmbedded() {
|
||||
this.contextRunner.run((context) -> {
|
||||
HibernateDefaultDdlAutoProvider ddlAutoProvider = new HibernateDefaultDdlAutoProvider(
|
||||
Collections.emptyList());
|
||||
assertThat(ddlAutoProvider.getDefaultDdlAuto(
|
||||
context.getBean(DataSource.class))).isEqualTo("create-drop");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultDDlAutoForEmbeddedWithPositiveContributor() {
|
||||
this.contextRunner.run((context) -> {
|
||||
DataSource dataSource = context.getBean(DataSource.class);
|
||||
SchemaManagementProvider provider = mock(SchemaManagementProvider.class);
|
||||
given(provider.getSchemaManagement(dataSource))
|
||||
.willReturn(SchemaManagement.MANAGED);
|
||||
HibernateDefaultDdlAutoProvider ddlAutoProvider = new HibernateDefaultDdlAutoProvider(
|
||||
Collections.singletonList(provider));
|
||||
assertThat(ddlAutoProvider.getDefaultDdlAuto(
|
||||
dataSource)).isEqualTo("none");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultDDlAutoForEmbeddedWithNegativeContributor() {
|
||||
this.contextRunner.run((context) -> {
|
||||
DataSource dataSource = context.getBean(DataSource.class);
|
||||
SchemaManagementProvider provider = mock(SchemaManagementProvider.class);
|
||||
given(provider.getSchemaManagement(dataSource))
|
||||
.willReturn(SchemaManagement.UNMANAGED);
|
||||
HibernateDefaultDdlAutoProvider ddlAutoProvider = new HibernateDefaultDdlAutoProvider(
|
||||
Collections.singletonList(provider));
|
||||
assertThat(ddlAutoProvider.getDefaultDdlAuto(
|
||||
dataSource)).isEqualTo("create-drop");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -101,6 +101,13 @@ public class HibernateJpaAutoConfigurationTests
|
|||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlywaySwitchOffDdlAuto() throws Exception {
|
||||
load(new Class<?>[0], new Class<?>[] { FlywayAutoConfiguration.class },
|
||||
"spring.datasource.initialize:false",
|
||||
"spring.flyway.locations:classpath:db/city");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlywayPlusValidation() throws Exception {
|
||||
load(new Class<?>[0], new Class<?>[] { FlywayAutoConfiguration.class },
|
||||
|
|
|
@ -62,7 +62,7 @@ public class JpaPropertiesTests {
|
|||
public void noCustomNamingStrategy() throws Exception {
|
||||
JpaProperties properties = load();
|
||||
Map<String, String> hibernateProperties = properties
|
||||
.getHibernateProperties(mockStandaloneDataSource());
|
||||
.getHibernateProperties("none");
|
||||
assertThat(hibernateProperties)
|
||||
.doesNotContainKeys("hibernate.ejb.naming_strategy");
|
||||
assertThat(hibernateProperties).containsEntry(
|
||||
|
@ -79,7 +79,7 @@ public class JpaPropertiesTests {
|
|||
"spring.jpa.hibernate.naming.implicit-strategy:com.example.Implicit",
|
||||
"spring.jpa.hibernate.naming.physical-strategy:com.example.Physical");
|
||||
Map<String, String> hibernateProperties = properties
|
||||
.getHibernateProperties(mockStandaloneDataSource());
|
||||
.getHibernateProperties("none");
|
||||
assertThat(hibernateProperties).contains(
|
||||
entry("hibernate.implicit_naming_strategy", "com.example.Implicit"),
|
||||
entry("hibernate.physical_naming_strategy", "com.example.Physical"));
|
||||
|
@ -93,7 +93,7 @@ public class JpaPropertiesTests {
|
|||
"spring.jpa.properties.hibernate.implicit_naming_strategy:com.example.Implicit",
|
||||
"spring.jpa.properties.hibernate.physical_naming_strategy:com.example.Physical");
|
||||
Map<String, String> hibernateProperties = properties
|
||||
.getHibernateProperties(mockStandaloneDataSource());
|
||||
.getHibernateProperties("none");
|
||||
// You can override them as we don't provide any default
|
||||
assertThat(hibernateProperties).contains(
|
||||
entry("hibernate.implicit_naming_strategy", "com.example.Implicit"),
|
||||
|
@ -106,7 +106,7 @@ public class JpaPropertiesTests {
|
|||
public void useNewIdGeneratorMappingsDefault() throws Exception {
|
||||
JpaProperties properties = load();
|
||||
Map<String, String> hibernateProperties = properties
|
||||
.getHibernateProperties(mockStandaloneDataSource());
|
||||
.getHibernateProperties("none");
|
||||
assertThat(hibernateProperties)
|
||||
.containsEntry(AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "true");
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ public class JpaPropertiesTests {
|
|||
JpaProperties properties = load(
|
||||
"spring.jpa.hibernate.use-new-id-generator-mappings:false");
|
||||
Map<String, String> hibernateProperties = properties
|
||||
.getHibernateProperties(mockStandaloneDataSource());
|
||||
.getHibernateProperties("none");
|
||||
assertThat(hibernateProperties)
|
||||
.containsEntry(AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "false");
|
||||
}
|
||||
|
|
|
@ -740,7 +740,7 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.jpa.database= # Target database to operate on, auto-detected by default. Can be alternatively set using the "databasePlatform" property.
|
||||
spring.jpa.database-platform= # Name of the target database to operate on, auto-detected by default. Can be alternatively set using the "Database" enum.
|
||||
spring.jpa.generate-ddl=false # Initialize the schema on startup.
|
||||
spring.jpa.hibernate.ddl-auto= # DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property. Default to "create-drop" when using an embedded database, "none" otherwise.
|
||||
spring.jpa.hibernate.ddl-auto= # DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property. Default to "create-drop" when using an embedded database and no schema manager was detected, "none" otherwise.
|
||||
spring.jpa.hibernate.naming.implicit-strategy= # Hibernate 5 implicit naming strategy fully qualified name.
|
||||
spring.jpa.hibernate.naming.physical-strategy= # Hibernate 5 physical naming strategy fully qualified name.
|
||||
spring.jpa.hibernate.use-new-id-generator-mappings= # Use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE.
|
||||
|
|
|
@ -1671,7 +1671,10 @@ configuration properties. Some of them are automatically detected according to t
|
|||
so you shouldn't have to set them.
|
||||
|
||||
The `spring.jpa.hibernate.ddl-auto` is a special case in that it has different defaults
|
||||
depending on whether you are using an embedded database (`create-drop`) or not (`none`).
|
||||
depending on runtime conditions. If an embedded database is used and no schema manager,
|
||||
such as Liquibase or Flyway, is handling the `DataSource` it then defaults to
|
||||
`create-drop`. In all other cases it defaults to `none`.
|
||||
|
||||
The dialect to use is also automatically detected based on the current `DataSource` but
|
||||
you can set `spring.jpa.database` yourself if you want to be explicit and bypass that
|
||||
check on startup.
|
||||
|
@ -1890,12 +1893,13 @@ database. This is controlled through two external properties:
|
|||
=== Initialize a database using Hibernate
|
||||
You can set `spring.jpa.hibernate.ddl-auto` explicitly and the standard Hibernate property
|
||||
values are `none`, `validate`, `update`, `create`, `create-drop`. Spring Boot chooses a
|
||||
default value for you based on whether it thinks your database is embedded (default
|
||||
`create-drop`) or not (default `none`). An embedded database is detected by looking at the
|
||||
`Connection` type: `hsqldb`, `h2` and `derby` are embedded, the rest are not. Be careful
|
||||
when switching from in-memory to a '`real`' database that you don't make assumptions about
|
||||
the existence of the tables and data in the new platform. You either have to set `ddl-auto`
|
||||
explicitly, or use one of the other mechanisms to initialize the database.
|
||||
default value for you based on whether it thinks your database is embedded: default to
|
||||
`create-drop` if no schema manager has been detected, `none` in all other cases. An
|
||||
embedded database is detected by looking at the `Connection` type: `hsqldb`, `h2` and
|
||||
`derby` are embedded, the rest are not. Be careful when switching from in-memory to a
|
||||
'`real`' database that you don't make assumptions about the existence of the tables and
|
||||
data in the new platform. You either have to set `ddl-auto` explicitly, or use one of the
|
||||
other mechanisms to initialize the database.
|
||||
|
||||
NOTE: You can output the schema creation by enabling the `org.hibernate.SQL` logger. This
|
||||
is done for you automatically if you enable the <<boot-features-logging-console-output,debug mode>>.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
management.security.enabled=false
|
||||
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
|
||||
spring.h2.console.enabled=true
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.jdbc;
|
||||
|
||||
/**
|
||||
* An enumeration of the available schema management options.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public enum SchemaManagement {
|
||||
|
||||
/**
|
||||
* The schema is managed and will be created at the appropriate time.
|
||||
*/
|
||||
MANAGED,
|
||||
|
||||
/**
|
||||
* The schema is not managed.
|
||||
*/
|
||||
UNMANAGED
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.jdbc;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* Strategy interface to determine the {@link SchemaManagement} of a {@link DataSource}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface SchemaManagementProvider {
|
||||
|
||||
/**
|
||||
* Return the {@link SchemaManagement} for the specified {@link DataSource}.
|
||||
* @param dataSource the dataSource to handle
|
||||
* @return the {@link SchemaManagement} for the {@link DataSource}.
|
||||
*/
|
||||
SchemaManagement getSchemaManagement(DataSource dataSource);
|
||||
|
||||
}
|
Loading…
Reference in New Issue