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

74

目前,我正在使用默认的@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

自从JPA 2.1以来,我应该能够使用javax.persistence.schema-generation.*属性,但将它们设置在我的application.properties中似乎没有任何效果。

我看到过像这样的示例,它连接了一堆额外的bean,但它们没有使用Mysql。而且无论如何,像那样做都需要我配置许多Spring现在正在为我处理的选项。

我的目标是:

  • 生成一个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

(使用Gradle,而不是Maven)

4个回答

132

啊,就在我发布这个问题后,Spring Data文档的一个部分引起了我的注意:

73.5 配置JPA属性,此外,spring.jpa.properties.* 中的所有属性在本地EntityManagerFactory创建时都作为普通的JPA属性传递(前缀已被去除)。

因此,回答我的问题:将javax.persistence属性的前缀改为spring.jpa.properties:

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
在执行此操作后,模式文件会自动生成在项目根目录中。

2
你在Spring配置中添加这些属性就足以得到你想要的结果了吗?还是你还需要编写一些Java代码来调用类似 Persistence.generateSchema(...) 的方法?如果可以分享的话,我很想看看你的解决方案的更多细节。 - Firefly
10
我看到该文件是在运行时生成的。有没有一种“离线”生成它的方法? - Alessandro Dionisi
5
能否在每个 DDL 命令后添加分号?是否可以在不使用 create-drop/create DDL 的情况下运行此命令?是否可以在不运行整个应用程序的情况下运行此命令? - Michail Michailidis
4
我想做的是将DDL生成到文本文件中,以便更轻松地设置Flyway迁移的样板工作,而不是自动执行它。 - Wouter Lievens
3
如果我想获取现有数据库的 "update.sql" 而不是创建空数据库的 DDL,该怎么办? - Ismail Yavuz
显示剩余10条评论

19

这是用于在根目录下生成 Spring Boot 数据库定义语言(DDL)创建脚本的 YML 配置:

这是特定于 yml 的配置,用于让 Spring Boot 在根文件夹中生成 DDL 创建脚本:

spring:
  jpa:
    properties:
      javax:
        persistence:
          schema-generation:
            create-source: metadata
            scripts:
              action: create
              create-target: create.sql

10
请提供一些信息以便我回答您的问题。 - Jim Jones
下面是 *.properties 文件的相应配置:spring.jpa.properties.javax.persistence.schema-generation.create-source=metadataspring.jpa.properties.javax.persistence.schema-generation.scripts.action=createspring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql - Orkhan Hasanli
它附加而不是替换文件。这个能改变吗? - Adriano dos Santos Fernandes

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);
    }
}

0

更新你的jpa属性将为你生成脚本。

            <prop key="javax.persistence.schema-generation.scripts.action">drop-and-create</prop>
            <prop key="javax.persistence.schema-generation.scripts.create-target">./create_mssql.sql</prop>
            <prop key="javax.persistence.schema-generation.scripts.drop-target">./drop_mssql.sql</prop>

这将在给定位置生成脚本。还有其他属性可以用于各种用例,请参考此处

整个配置将如下所示

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="my-persistence-unit" transaction-type="JTA">
    <description>Forge Persistence Unit</description>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>

      <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
      <property name="javax.persistence.sql-load-script-source" value="META-INF/data.sql"/>
    </properties>
  </persistence-unit>
</persistence>

你在询问为什么它不能工作 https://stackoverflow.com/questions/55275380/not-able-to-generate-ddl-schema-for-my-spring-entites-in-my-spring-application/55286744#55286744 并发布相同的答案? - Peter Šály
我找到了答案,是属性被遗漏了。 - JITHIN_PATHROSE
你能提供更多结构化的代码示例吗?我将你的示例放在了aplicationContext.xml文件中的org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean下的jpaProperties部分,但是它没有起作用。 - hariprasad
我已经添加了整个配置文件。 - JITHIN_PATHROSE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接