From 40d374978f5c156b7205f31626392d9b335cc545 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Sun, 7 Apr 2024 17:53:49 +0800 Subject: [PATCH] Don't override `spring.jpa.generate-ddl` if `spring.jpa.properties.hibernate.hbm2ddl.auto` is not set Fix GH-40177 --- .../orm/jpa/HibernateProperties.java | 15 ++++++---- .../HibernateJpaAutoConfigurationTests.java | 30 ++++++++++++++++++- .../modules/reference/pages/data/sql.adoc | 2 +- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateProperties.java index d155a00c2b00..06cd0caa4575 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -36,6 +36,7 @@ * * @author Stephane Nicoll * @author Chris Bono + * @author Yanming Zhou * @since 2.1.0 * @see JpaProperties */ @@ -85,11 +86,13 @@ private Map getAdditionalProperties(Map existing applyScanner(result); getNaming().applyNamingStrategies(result); String ddlAuto = determineDdlAuto(existing, settings::getDdlAuto); - if (StringUtils.hasText(ddlAuto) && !"none".equals(ddlAuto)) { - result.put(AvailableSettings.HBM2DDL_AUTO, ddlAuto); - } - else { - result.remove(AvailableSettings.HBM2DDL_AUTO); + if (StringUtils.hasText(ddlAuto)) { + if (!"none".equals(ddlAuto)) { + result.put(AvailableSettings.HBM2DDL_AUTO, ddlAuto); + } + else { + result.remove(AvailableSettings.HBM2DDL_AUTO); + } } Collection customizers = settings.getHibernatePropertiesCustomizers(); if (!ObjectUtils.isEmpty(customizers)) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java index b5c385699f95..4787e7bcb197 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -40,6 +40,7 @@ import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.PhysicalNamingStrategy; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.ManagedBeanSettings; import org.hibernate.cfg.SchemaToolingSettings; import org.hibernate.dialect.H2Dialect; @@ -76,6 +77,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -98,6 +100,7 @@ * @author Stephane Nicoll * @author Chris Bono * @author Moritz Halbritter + * @author Yanming Zhou */ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTests { @@ -182,6 +185,31 @@ void hibernateDialectIsSetWhenDatabasePlatformIsSet() { .contains(entry("hibernate.dialect", databasePlatform)))); } + @Test + void jpaGenerateDdlIsUsedIfHibernateHbm2ddlAutoIsNotSet() { + contextRunner().withPropertyValues("spring.jpa.generate-ddl=true") + .run(assertEntityManagerFactoryBean((adapter) -> assertThat(adapter.getJpaPropertyMap()) + .doesNotContainEntry(AvailableSettings.HBM2DDL_AUTO, "none"))); + } + + @Test + void jpaGenerateDdlIsNotUsedIfHibernateHbm2ddlAutoIsSet() { + contextRunner() + .withPropertyValues("spring.jpa.generate-ddl=true", "spring.jpa.properties.hibernate.hbm2ddl.auto=none") + .run(assertEntityManagerFactoryBean((adapter) -> assertThat(adapter.getJpaPropertyMap()) + .containsEntry(AvailableSettings.HBM2DDL_AUTO, "none"))); + } + + private ContextConsumer assertEntityManagerFactoryBean( + Consumer adapter) { + return (context) -> { + assertThat(context).hasSingleBean(JpaVendorAdapter.class); + assertThat(context).hasSingleBean(HibernateJpaVendorAdapter.class); + assertThat(context).hasSingleBean(AbstractEntityManagerFactoryBean.class); + adapter.accept(context.getBean(AbstractEntityManagerFactoryBean.class)); + }; + } + private ContextConsumer assertJpaVendorAdapter( Consumer adapter) { return (context) -> { diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/data/sql.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/data/sql.adoc index 71bb7b1f3de6..0c28e5c9ed98 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/data/sql.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/data/sql.adoc @@ -307,7 +307,7 @@ spring: The line in the preceding example passes a value of `true` for the `hibernate.globally_quoted_identifiers` property to the Hibernate entity manager. By default, the DDL execution (or validation) is deferred until the `ApplicationContext` has started. -There is also a `spring.jpa.generate-ddl` flag, but it is not used if Hibernate auto-configuration is active, because the `ddl-auto` settings are more fine-grained. +There is also a `spring.jpa.generate-ddl` flag, but it is not used if `spring.jpa.properties.hibernate.hbm2ddl.auto` is present, because the latter are more fine-grained.