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:
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user