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 ac0fc1c9f77..d1ddd7e0097 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 @@ -46,7 +46,6 @@ import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.jpa.HibernatePersistenceProvider; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.aot.hint.MemberCategory; @@ -76,7 +75,6 @@ import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -510,88 +508,6 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes } } - @Test - @Disabled("gh-40177") - void whenSpringJpaGenerateDdlIsNotSetThenTableIsNotCreated() { - // spring.jpa.generated-ddl defaults to false but this test still fails because - // we're using an embedded database which means that HibernateProperties defaults - // hibernate.hbm2ddl.auto to create-drop, replacing the - // hibernate.hbm2ddl.auto=none that comes from generate-ddl being false. - contextRunner().run((context) -> assertThat(tablesFrom(context)).doesNotContain("CITY")); - } - - @Test - void whenSpringJpaGenerateDdlIsTrueThenTableIsCreated() { - contextRunner().withPropertyValues("spring.jpa.generate-ddl=true") - .run((context) -> assertThat(tablesFrom(context)).contains("CITY")); - } - - @Test - @Disabled("gh-40177") - void whenSpringJpaGenerateDdlIsFalseThenTableIsNotCreated() { - // This test fails because we're using an embedded database which means that - // HibernateProperties defaults hibernate.hbm2ddl.auto to create-drop, replacing - // the hibernate.hbm2ddl.auto=none that comes from setting generate-ddl to false. - contextRunner().withPropertyValues("spring.jpa.generate-ddl=false") - .run((context) -> assertThat(tablesFrom(context)).doesNotContain("CITY")); - } - - @Test - void whenHbm2DdlAutoIsNoneThenTableIsNotCreated() { - contextRunner().withPropertyValues("spring.jpa.properties.hibernate.hbm2ddl.auto=none") - .run((context) -> assertThat(tablesFrom(context)).doesNotContain("CITY")); - } - - @Test - void whenSpringJpaHibernateDdlAutoIsNoneThenTableIsNotCreated() { - contextRunner().withPropertyValues("spring.jpa.hibernate.ddl-auto=none") - .run((context) -> assertThat(tablesFrom(context)).doesNotContain("CITY")); - } - - @Test - @Disabled("gh-40177") - void whenSpringJpaGenerateDdlIsTrueAndSpringJpaHibernateDdlAutoIsNoneThenTableIsNotCreated() { - // This test fails because when ddl-auto is set to none, we remove - // hibernate.hbm2ddl.auto from Hibernate properties. This then allows - // spring.jpa.generate-ddl to set it to create-drop - contextRunner().withPropertyValues("spring.jpa.generate-ddl=true", "spring.jpa.hibernate.ddl-auto=none") - .run((context) -> assertThat(tablesFrom(context)).doesNotContain("CITY")); - } - - @Test - void whenSpringJpaGenerateDdlIsTrueAndSpringJpaHibernateDdlAutoIsDropThenTableIsNotCreated() { - contextRunner().withPropertyValues("spring.jpa.generate-ddl=true", "spring.jpa.hibernate.ddl-auto=drop") - .run((context) -> assertThat(tablesFrom(context)).doesNotContain("CITY")); - } - - @Test - void whenSpringJpaGenerateDdlIsTrueAndJakartaSchemaGenerationIsNoneThenTableIsNotCreated() { - contextRunner() - .withPropertyValues("spring.jpa.generate-ddl=true", - "spring.jpa.properties.jakarta.persistence.schema-generation.database.action=none") - .run((context) -> { - assertThat(tablesFrom(context)).doesNotContain("CITY"); - }); - } - - @Test - void whenSpringJpaGenerateDdlIsTrueSpringJpaHibernateDdlAutoIsCreateAndJakartaSchemaGenerationIsNoneThenTableIsNotCreated() { - contextRunner() - .withPropertyValues("spring.jpa.generate-ddl=true", "spring.jpa.hibernate.ddl-auto=create", - "spring.jpa.properties.jakarta.persistence.schema-generation.database.action=none") - .run((context) -> { - assertThat(tablesFrom(context)).doesNotContain("CITY"); - }); - } - - private List tablesFrom(AssertableApplicationContext context) { - DataSource dataSource = context.getBean(DataSource.class); - JdbcTemplate jdbc = new JdbcTemplate(dataSource); - List tables = jdbc.query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES", - (results, row) -> results.getString(1)); - return tables; - } - @Configuration(proxyBeanMethods = false) @TestAutoConfigurationPackage(City.class) @DependsOnDatabaseInitialization diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties index 1b940ae7f85..e29b38c8e5f 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties @@ -1041,6 +1041,3 @@ features.testing.testcontainers.at-development-time=features.testcontainers.at-d features.testing.testcontainers.at-development-time.dynamic-properties=features.testcontainers.at-development-time.dynamic-properties features.testing.testcontainers.at-development-time.importing-container-declarations=features.testcontainers.at-development-time.importing-container-declarations features.testing.testcontainers.at-development-time.devtools=features.testcontainers.at-development-time.devtools - -# gh-40503 -howto.data-initialization.using-jpa=howto.data-initialization.using-hibernate diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/sql.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/sql.adoc index a460857d2ab..8d59561c5f1 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/sql.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/sql.adoc @@ -282,6 +282,7 @@ The following line shows an example of setting JPA properties for Hibernate: 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. diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/data-initialization.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/data-initialization.adoc index 12d0c0af136..fcb20a4e5b7 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/data-initialization.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/data-initialization.adoc @@ -6,17 +6,24 @@ It is recommended to use a single mechanism for schema generation. +[[howto.data-initialization.using-jpa]] +=== Initialize a Database Using JPA +JPA has features for DDL generation, and these can be set up to run on startup against the database. +This is controlled through two external properties: + +* `spring.jpa.generate-ddl` (boolean) switches the feature on and off and is vendor independent. +* `spring.jpa.hibernate.ddl-auto` (enum) is a Hibernate feature that controls the behavior in a more fine-grained way. + This feature is described in more detail later in this guide. + + [[howto.data-initialization.using-hibernate]] === Initialize a Database Using Hibernate -You can set configprop:spring.jpa.hibernate.ddl-auto[] to control Hibernate's database initialization. -Supported values are `none`, `validate`, `update`, `create`, and `create-drop`. -Spring Boot chooses a default value for you based on whether you are using an embedded database. -An embedded database is identified by looking at the `Connection` type and JDBC url. -`hsqldb`, `h2`, or `derby` are embedded databases and others are not. -If an embedded database is identified and no schema manager (Flyway or Liquibase) has been detected, `ddl-auto` defaults to `create-drop`. -In all other cases, it defaults to `none`. - +You can set `spring.jpa.hibernate.ddl-auto` explicitly and the standard Hibernate property values are `none`, `validate`, `update`, `create`, and `create-drop`. +Spring Boot chooses a default value for you based on whether it thinks your database is embedded. +It defaults to `create-drop` if no schema manager has been detected or `none` in all other cases. +An embedded database is detected by looking at the `Connection` type and JDBC url. +`hsqldb`, `h2`, and `derby` are candidates, and others are not. Be careful when switching from in-memory to a '`real`' database that you do not 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.