Commit 0207b816 authored by Stephane Nicoll's avatar Stephane Nicoll

Attempt to detect ddl-auto mode only if necessary

This commit defers the resolution of the default ddl auto mode only when
it is absolutely necessary. This prevents Spring Boot to attempt to get
a connection when it isn't necessary

Closes gh-12374
parent 317b51f2
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.orm.jpa; package org.springframework.boot.autoconfigure.orm.jpa;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource; import javax.sql.DataSource;
...@@ -90,8 +91,9 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { ...@@ -90,8 +91,9 @@ class DataSourceInitializedPublisher implements BeanPostProcessor {
if (this.properties == null) { if (this.properties == null) {
return true; // better safe than sorry return true; // better safe than sorry
} }
String defaultDdlAuto = (EmbeddedDatabaseConnection.isEmbedded(dataSource) Supplier<String> defaultDdlAuto = () ->
? "create-drop" : "none"); EmbeddedDatabaseConnection.isEmbedded(dataSource) ? "create-drop"
: "none";
Map<String, Object> hibernate = this.properties Map<String, Object> hibernate = this.properties
.getHibernateProperties(new HibernateSettings().ddlAuto(defaultDdlAuto)); .getHibernateProperties(new HibernateSettings().ddlAuto(defaultDdlAuto));
if (hibernate.containsKey("hibernate.hbm2ddl.auto")) { if (hibernate.containsKey("hibernate.hbm2ddl.auto")) {
......
...@@ -21,6 +21,7 @@ import java.util.Collections; ...@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier;
import javax.sql.DataSource; import javax.sql.DataSource;
...@@ -116,7 +117,7 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -116,7 +117,7 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
@Override @Override
protected Map<String, Object> getVendorProperties() { protected Map<String, Object> getVendorProperties() {
String defaultDdlMode = this.defaultDdlAutoProvider Supplier<String> defaultDdlMode = () -> this.defaultDdlAutoProvider
.getDefaultDdlAuto(getDataSource()); .getDefaultDdlAuto(getDataSource());
return new LinkedHashMap<>(getProperties() return new LinkedHashMap<>(getProperties()
.getHibernateProperties(new HibernateSettings().ddlAuto(defaultDdlMode) .getHibernateProperties(new HibernateSettings().ddlAuto(defaultDdlMode)
......
...@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.orm.jpa; ...@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.orm.jpa;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.function.Supplier;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
...@@ -30,7 +31,7 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy; ...@@ -30,7 +31,7 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
*/ */
public class HibernateSettings { public class HibernateSettings {
private String ddlAuto; private Supplier<String> ddlAuto;
private ImplicitNamingStrategy implicitNamingStrategy; private ImplicitNamingStrategy implicitNamingStrategy;
...@@ -38,13 +39,25 @@ public class HibernateSettings { ...@@ -38,13 +39,25 @@ public class HibernateSettings {
private Collection<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers; private Collection<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers;
public HibernateSettings ddlAuto(String ddlAuto) { public HibernateSettings ddlAuto(Supplier<String> ddlAuto) {
this.ddlAuto = ddlAuto; this.ddlAuto = ddlAuto;
return this; return this;
} }
/**
* Specify the default ddl auto value to use.
* @param ddlAuto the default ddl auto if none is provided
* @return this instance
* @see #ddlAuto(Supplier)
* @deprecated as of 2.0.1 in favour of {@link #ddlAuto(Supplier)}
*/
@Deprecated
public HibernateSettings ddlAuto(String ddlAuto) {
return ddlAuto(() -> ddlAuto);
}
public String getDdlAuto() { public String getDdlAuto() {
return this.ddlAuto; return (this.ddlAuto != null ? this.ddlAuto.get() : null);
} }
public HibernateSettings implicitNamingStrategy( public HibernateSettings implicitNamingStrategy(
......
...@@ -22,6 +22,7 @@ import java.util.HashMap; ...@@ -22,6 +22,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.inject.Provider;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
...@@ -217,7 +218,7 @@ public class JpaProperties { ...@@ -217,7 +218,7 @@ public class JpaProperties {
getNaming().applyNamingStrategies(result, getNaming().applyNamingStrategies(result,
settings.getImplicitNamingStrategy(), settings.getImplicitNamingStrategy(),
settings.getPhysicalNamingStrategy()); settings.getPhysicalNamingStrategy());
String ddlAuto = determineDdlAuto(existing, settings.getDdlAuto()); String ddlAuto = determineDdlAuto(existing, settings::getDdlAuto);
if (StringUtils.hasText(ddlAuto) && !"none".equals(ddlAuto)) { if (StringUtils.hasText(ddlAuto) && !"none".equals(ddlAuto)) {
result.put("hibernate.hbm2ddl.auto", ddlAuto); result.put("hibernate.hbm2ddl.auto", ddlAuto);
} }
...@@ -243,11 +244,13 @@ public class JpaProperties { ...@@ -243,11 +244,13 @@ public class JpaProperties {
} }
private String determineDdlAuto(Map<String, String> existing, private String determineDdlAuto(Map<String, String> existing,
String defaultDdlAuto) { Provider<String> defaultDdlAuto) {
String ddlAuto = (this.ddlAuto != null ? this.ddlAuto : defaultDdlAuto); if (!existing.containsKey("hibernate.hbm2ddl.auto")) {
if (!existing.containsKey("hibernate.hbm2ddl.auto") String ddlAuto = (this.ddlAuto != null ? this.ddlAuto
&& !"none".equals(ddlAuto)) { : defaultDdlAuto.get());
return ddlAuto; if (!"none".equals(ddlAuto)) {
return ddlAuto;
}
} }
if (existing.containsKey("hibernate.hbm2ddl.auto")) { if (existing.containsKey("hibernate.hbm2ddl.auto")) {
return existing.get("hibernate.hbm2ddl.auto"); return existing.get("hibernate.hbm2ddl.auto");
......
...@@ -69,7 +69,7 @@ public class CustomHibernateJpaAutoConfigurationTests { ...@@ -69,7 +69,7 @@ public class CustomHibernateJpaAutoConfigurationTests {
.run((context) -> { .run((context) -> {
JpaProperties bean = context.getBean(JpaProperties.class); JpaProperties bean = context.getBean(JpaProperties.class);
Map<String, Object> hibernateProperties = bean.getHibernateProperties( Map<String, Object> hibernateProperties = bean.getHibernateProperties(
new HibernateSettings().ddlAuto("create-drop")); new HibernateSettings());
assertThat(hibernateProperties.get("hibernate.ejb.naming_strategy")) assertThat(hibernateProperties.get("hibernate.ejb.naming_strategy"))
.isNull(); .isNull();
}); });
......
...@@ -22,6 +22,7 @@ import java.sql.SQLException; ...@@ -22,6 +22,7 @@ import java.sql.SQLException;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import javax.sql.DataSource; import javax.sql.DataSource;
...@@ -60,7 +61,7 @@ public class JpaPropertiesTests { ...@@ -60,7 +61,7 @@ public class JpaPropertiesTests {
public void noCustomNamingStrategy() { public void noCustomNamingStrategy() {
this.contextRunner.run(assertJpaProperties((properties) -> { this.contextRunner.run(assertJpaProperties((properties) -> {
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties(new HibernateSettings().ddlAuto("none")); .getHibernateProperties(new HibernateSettings());
assertThat(hibernateProperties) assertThat(hibernateProperties)
.doesNotContainKeys("hibernate.ejb.naming_strategy"); .doesNotContainKeys("hibernate.ejb.naming_strategy");
assertThat(hibernateProperties).containsEntry( assertThat(hibernateProperties).containsEntry(
...@@ -80,7 +81,7 @@ public class JpaPropertiesTests { ...@@ -80,7 +81,7 @@ public class JpaPropertiesTests {
.run(assertJpaProperties((properties) -> { .run(assertJpaProperties((properties) -> {
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(
new HibernateSettings().ddlAuto("none")); new HibernateSettings());
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", entry("hibernate.implicit_naming_strategy",
"com.example.Implicit"), "com.example.Implicit"),
...@@ -97,7 +98,7 @@ public class JpaPropertiesTests { ...@@ -97,7 +98,7 @@ public class JpaPropertiesTests {
ImplicitNamingStrategy implicitStrategy = mock(ImplicitNamingStrategy.class); ImplicitNamingStrategy implicitStrategy = mock(ImplicitNamingStrategy.class);
PhysicalNamingStrategy physicalStrategy = mock(PhysicalNamingStrategy.class); PhysicalNamingStrategy physicalStrategy = mock(PhysicalNamingStrategy.class);
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties(new HibernateSettings().ddlAuto("none") .getHibernateProperties(new HibernateSettings()
.implicitNamingStrategy(implicitStrategy) .implicitNamingStrategy(implicitStrategy)
.physicalNamingStrategy(physicalStrategy)); .physicalNamingStrategy(physicalStrategy));
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
...@@ -120,7 +121,7 @@ public class JpaPropertiesTests { ...@@ -120,7 +121,7 @@ public class JpaPropertiesTests {
PhysicalNamingStrategy.class); PhysicalNamingStrategy.class);
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(
new HibernateSettings().ddlAuto("none") new HibernateSettings()
.implicitNamingStrategy(implicitStrategy) .implicitNamingStrategy(implicitStrategy)
.physicalNamingStrategy(physicalStrategy)); .physicalNamingStrategy(physicalStrategy));
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
...@@ -154,7 +155,7 @@ public class JpaPropertiesTests { ...@@ -154,7 +155,7 @@ public class JpaPropertiesTests {
}; };
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(
new HibernateSettings().ddlAuto("none") new HibernateSettings()
.implicitNamingStrategy(implicitStrategy) .implicitNamingStrategy(implicitStrategy)
.physicalNamingStrategy(physicalStrategy) .physicalNamingStrategy(physicalStrategy)
.hibernatePropertiesCustomizers( .hibernatePropertiesCustomizers(
...@@ -177,7 +178,7 @@ public class JpaPropertiesTests { ...@@ -177,7 +178,7 @@ public class JpaPropertiesTests {
.run(assertJpaProperties((properties) -> { .run(assertJpaProperties((properties) -> {
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(
new HibernateSettings().ddlAuto("none")); new HibernateSettings());
// You can override them as we don't provide any default // You can override them as we don't provide any default
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", entry("hibernate.implicit_naming_strategy",
...@@ -193,7 +194,7 @@ public class JpaPropertiesTests { ...@@ -193,7 +194,7 @@ public class JpaPropertiesTests {
public void useNewIdGeneratorMappingsDefault() { public void useNewIdGeneratorMappingsDefault() {
this.contextRunner.run(assertJpaProperties((properties) -> { this.contextRunner.run(assertJpaProperties((properties) -> {
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties(new HibernateSettings().ddlAuto("none")); .getHibernateProperties(new HibernateSettings());
assertThat(hibernateProperties).containsEntry( assertThat(hibernateProperties).containsEntry(
AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "true"); AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "true");
})); }));
...@@ -207,7 +208,7 @@ public class JpaPropertiesTests { ...@@ -207,7 +208,7 @@ public class JpaPropertiesTests {
.run(assertJpaProperties((properties) -> { .run(assertJpaProperties((properties) -> {
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(
new HibernateSettings().ddlAuto("none")); new HibernateSettings());
assertThat(hibernateProperties).containsEntry( assertThat(hibernateProperties).containsEntry(
AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "false"); AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "false");
})); }));
...@@ -248,6 +249,33 @@ public class JpaPropertiesTests { ...@@ -248,6 +249,33 @@ public class JpaPropertiesTests {
})); }));
} }
@Test
public void defaultDdlAutoIsNotInvokedIfPropertyIsSet() {
this.contextRunner
.withPropertyValues("spring.jpa.hibernate.ddl-auto=validate")
.run(assertDefaultDdlAutoNotInvoked("validate"));
}
@Test
public void defaultDdlAutoIsNotInvokedIfHibernateSpecificPropertyIsSet() {
this.contextRunner
.withPropertyValues("spring.jpa.properties.hibernate.hbm2ddl.auto=create")
.run(assertDefaultDdlAutoNotInvoked("create"));
}
private ContextConsumer<AssertableApplicationContext> assertDefaultDdlAutoNotInvoked(
String expectedDdlAuto) {
return assertJpaProperties((properties) -> {
Supplier<String> ddlAutoSupplier = mock(Supplier.class);
Map<String, Object> hibernateProperties = properties
.getHibernateProperties(new HibernateSettings()
.ddlAuto(ddlAutoSupplier));
assertThat(hibernateProperties).containsEntry(
"hibernate.hbm2ddl.auto", expectedDdlAuto);
verify(ddlAutoSupplier, never()).get();
});
}
@Test @Test
public void determineDatabaseWithUnknownUrl() { public void determineDatabaseWithUnknownUrl() {
this.contextRunner.run(assertJpaProperties((properties) -> { this.contextRunner.run(assertJpaProperties((properties) -> {
......
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