如何使用现代Spring Boot + Data JPA和Hibernate设置生成ddl创建脚本?

Cas*_*sey 44 hibernate spring-data spring-data-jpa spring-boot

目前,我正在使用@SpringBootApplication具有以下属性的默认注释application.properties:

spring.datasource.url=jdbc:mysql://localhost/dbname
spring.datasource.username=X
spring.datasource.password=X
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.naming_strategy=my.package.CustomNamingStrategy
Run Code Online (Sandbox Code Playgroud)

从JPA 2.1开始,我应该可以使用这些javax.persistence.schema-generation.*属性,但是在我的application.properties中设置它们似乎没有任何效果.

我见过的例子是这样那丝了一大堆额外的豆子,但他们没有使用MySQL.无论如何,这样做需要我配置春天为我提供的许多选项.

我的目标是:

  • 在MYSQL方言中生成模式创建sql脚本
  • 没有数据库连接是必需的
  • 输出构建目录中的脚本
  • 同时生成hibernate envers表也是一个巨大的优势.

我不想:

  • 在实时数据库上创建/删除模式

Lib版本:

   hibernate          : 4.3.11.FINAL
   spring framework   : 4.2.5.RELEASE
   spring-boot        : 1.3.3.RELEASE
   spring-data-jpa    : 1.10.1.RELEASE   // for  querydsl 4 support
   spring-data-commons: 1.12.1.RELEASE   // for  querydsl 4 support
Run Code Online (Sandbox Code Playgroud)

(使用gradle,而不是maven)

Cas*_*sey 90

啊,在我发布这个问题之后,弹簧数据文档的一部分引起了我的注意:

73.5配置JPA属性 此外,当创建本地EntityManagerFactory时,spring.jpa.properties.*中的所有属性都作为普通的JPA属性(带有前缀剥离)传递.

所以,回答我自己的问题:使用spring.jpa.properties为javax.persistence属性添加前缀:

spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata
spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql
Run Code Online (Sandbox Code Playgroud)

执行此操作后,模式文件在项目根目录中自动生成.

  • 我看到该文件是在运行时生成的.有没有办法让它"离线"生成? (5认同)
  • 有没有办法补充; 在每个ddl命令之后?是否有可能在没有create-drop/create ddl的情况下运行?是否可以在不运行整个应用程序的情况下运行? (3认同)
  • 如果我想获取现有数据库的“update.sql”而不是为空数据库创建 DDL,该怎么办? (3认同)
  • 如今,到 2023 年 8 月,您更有可能使用 Jakarta Persistence,因此属性名称将以“spring.jpa.properties.jakarta.persistence”开头,而不是“spring.jpa.properties.javax.persistence”。 ` (3认同)
  • 是否足以将这些属性添加到Spring配置中以获得您所获得的结果,或者您是否还必须编写一些Java代码来调用Persistence.generateSchema(...)之类的内容?如果你能分享,我们很乐意看到你的解决方案. (2认同)
  • 我想做的是将DDL生成为文本文件,以便更轻松地为Flyway迁移设置样板工作,而不是自动执行... (2认同)

小智 11

这是yml特定配置,用于使spring boot在根文件夹中生成ddl创建脚本:

spring:
  jpa:
    properties:
      javax:
        persistence:
          schema-generation:
            create-source: metadata
            scripts:
              action: create
              create-target: create.sql
Run Code Online (Sandbox Code Playgroud)

  • 请为您的答案提供一些信息。 (9认同)

Wer*_*her 6

以下代码将允许您以独立方式(独立于 Spring Boot)为所有发现的实体生成 DDL。这允许您生成架构而无需启动主应用程序。

它使用以下依赖项:

  • org.hibernate:hibernate-core
  • org.reflections:reflections
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.schema.TargetType;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;

import javax.persistence.Entity;
import java.util.EnumSet;
import java.util.Set;

public class SchemaGenerator {
    public static void main(String... args) {
        new SchemaGenerator().generateSchema();
    }

    private void generateSchema() {
        var serviceRegistry = new StandardServiceRegistryBuilder()
                .applySetting("hibernate.dialect", "<fully qualifified dialect class name>")
                .build();
        var entities = scanForEntities("<package1>", "<package2>");
        MetadataSources metadataSources = new MetadataSources(serviceRegistry);
        entities.forEach(metadataSources::addAnnotatedClass);
        Metadata metadata = metadataSources.buildMetadata();
        SchemaExport schemaExport = new SchemaExport();
        schemaExport.setFormat(true);
        schemaExport.setOutputFile("<output file name>");
        schemaExport.createOnly(EnumSet.of(TargetType.SCRIPT), metadata);
    }

    private Set<Class<?>> scanForEntities(String... packages) {
        var reflections = new Reflections(
                new ConfigurationBuilder()
                        .forPackages(packages)
        );
       return reflections.getTypesAnnotatedWith(Entity.class);
    }
}
Run Code Online (Sandbox Code Playgroud)