使用自定义分隔符生成具有弹簧引导的DDL

Ren*_*ink 7 ddl spring hibernate spring-data-jpa spring-boot

我想使用带有JPA - Hibernate 5.0.11的spring boot v1.4.3生成create和drop ddl脚本.

我找到的大多数答案都使用了javax.persistence.schema-generation属性.例如/sf/answers/2587649361/

这种方法的问题是它输出没有分隔符的sql语句.例如

create table ... (...)
create table ... (...)
Run Code Online (Sandbox Code Playgroud)

我希望它用分隔符输出语句 ;

create table ... (...);
create table ... (...);
Run Code Online (Sandbox Code Playgroud)

但我找不到任何javax.persistence.schema-generation属性来配置它.

所以我想使用SchemaExportfrom hibernate,因为你可以设置delimiter属性.但要创建一个SchemaExport我需要一个MetadataImplementor(非删除的api).

我无法弄清楚如何MetadataImplementor从春季靴子中获得一个.

有没有人知道是否有

  • javax.persistence.schema-generation用于定义分隔符的属性
  • 或者如何创建SchemaExport(获取依赖项)
  • 还是有其他解决方案?

这是您可以使用的一些代码

@SpringBootApplication
@ComponentScan(basePackageClasses = Application.class)
@EntityScan(basePackageClasses = User.class)
public class Application {

    @Bean
    public ApplicationRunner getApplicationRunner() {
        return new ApplicationRunner() {

            public void run(ApplicationArguments args) throws Exception {
                // MetadataImplementor metadataImplementor = ???;
                // new SchemaExport(metadataImplementor);
            }
        };
    }

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.run(args);
    }

}
Run Code Online (Sandbox Code Playgroud)

实体类

@Entity
public class User {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
Run Code Online (Sandbox Code Playgroud)

另一个实体类

@Entity
public class Person {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
Run Code Online (Sandbox Code Playgroud)

application.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
Run Code Online (Sandbox Code Playgroud)

maven依赖

<properties>
    <spring.boot.version>1.4.3.RELEASE</spring.boot.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
</dependencies>   
Run Code Online (Sandbox Code Playgroud)

使用Hibernate 5.0

我刚刚用hibernate尝试了上面的代码5.0.11.Final.你唯一必须改变的是

SchemaExport schemaExport = new SchemaExport((MetadataImplementor) metadata);
schemaExport.setDelimiter(";");
schemaExport.setFormat(false);
schemaExport.setOutputFile(dropAndCreateDdlFile.getAbsolutePath());

schemaExport.execute(true, false, false, false);
Run Code Online (Sandbox Code Playgroud)

或者当然让java配置返回MetadataImplementor而不是Metadata更改ApplicationRunner构造函数参数.

Ala*_*KER 6

您可能想尝试设置以下 Hibernate 属性:

spring.jpa.properties.hibernate.hbm2ddl.delimiter=;

#in addition to the other standard JPA properties you refered to, namely:
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)

我发现这是在Spring Boot 2.1.2.RELEASE + 匹配 Hibernate 版本(5.3.7.Final)项目中完成的工作,我需要相同的功能。

它可能非常适合您不太不同的 Hibernate 环境。


有点跑题,但我仍然存在一个问题:Hibernate附加到 create.sql。我希望我找到了一种方法来让它替换文件内容。


Ren*_*ink 5

最后经过大量调查,我想我找到了一个使用公共 API 的简单解决方案。我发现的解决方案使用休眠5.2(更具体5.2.6.Final)。但我认为它也可以适应5.0

这是我的spring java配置

@Configuration
@AutoConfigureAfter({ HibernateJpaAutoConfiguration.class })
public class HibernateJavaConfig {

    @ConditionalOnMissingBean({ Metadata.class })
    @Bean
    public Metadata getMetadata(StandardServiceRegistry standardServiceRegistry,
            PersistenceUnitInfo persistenceUnitInfo) {
        MetadataSources metadataSources = new MetadataSources(standardServiceRegistry);

        List<String> managedClassNames = persistenceUnitInfo.getManagedClassNames();
        for (String managedClassName : managedClassNames) {
            metadataSources.addAnnotatedClassName(managedClassName);
        }

        Metadata metadata = metadataSources.buildMetadata();
        return metadata;
    }

    @ConditionalOnMissingBean({ StandardServiceRegistry.class })
    @Bean
    public StandardServiceRegistry getStandardServiceRegistry(JpaProperties jpaProperties) {
        StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder();

        Map<String, String> properties = jpaProperties.getProperties();
        ssrb.applySettings(properties);

        StandardServiceRegistry ssr = ssrb.build();
        return ssr;
    }

    @ConditionalOnMissingBean({ PersistenceUnitInfo.class })
    @Bean
    public PersistenceUnitInfo getPersistenceUnitInfo(EntityScanPackages entityScanPackages) {
        List<String> packagesToScan = entityScanPackages.getPackageNames();

        DefaultPersistenceUnitManager persistenceUnitManager = new DefaultPersistenceUnitManager();

        String[] packagesToScanArr = (String[]) packagesToScan.toArray(new String[packagesToScan.size()]);
        persistenceUnitManager.setPackagesToScan(packagesToScanArr);
        persistenceUnitManager.afterPropertiesSet();

        PersistenceUnitInfo persistenceUnitInfo = persistenceUnitManager.obtainDefaultPersistenceUnitInfo();
        return persistenceUnitInfo;
    }

}
Run Code Online (Sandbox Code Playgroud)

java 配置创建了一个Metadatabean。这个 bean 可以在 hibernate 5.2 中使用来执行模式生成。例如

@Component
public class GenerateDDLApplicationRunner implements ApplicationRunner {

    private Metadata metadata;

    public GenerateDDLApplicationRunner(Metadata metadata) {
        this.metadata = metadata;
    }

    public void run(ApplicationArguments args) throws Exception {
        File dropAndCreateDdlFile = new File("drop-and-create.ddl");
        deleteFileIfExists(dropAndCreateDdlFile);

        SchemaExport schemaExport = new SchemaExport();
        schemaExport.setDelimiter(";");
        schemaExport.setFormat(false);
        schemaExport.setOutputFile(dropAndCreateDdlFile.getAbsolutePath());

        schemaExport.execute(EnumSet.of(TargetType.SCRIPT), Action.BOTH, metadata);
    }

    private void deleteFileIfExists(File dropAndCreateDdlFile) {
        if (dropAndCreateDdlFile.exists()) {
            if (!dropAndCreateDdlFile.isFile()) {
                String msg = MessageFormat.format("File is not a normal file {0}", dropAndCreateDdlFile);
                throw new IllegalStateException(msg);
            }

            if (!dropAndCreateDdlFile.delete()) {
                String msg = MessageFormat.format("Unable to delete file {0}", dropAndCreateDdlFile);
                throw new IllegalStateException(msg);
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

休眠方言是使用 spring boot 配置的application.properties。就我而言:

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL57InnoDBDialect
Run Code Online (Sandbox Code Playgroud)