本文介绍了使用自定义分隔符通过弹簧引导生成DDL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我发现的大多数答案都使用 javax.persistence.schema-generation 属性。例如。





  create table ...(...)
create table ...(...)

我希望它输出分隔符;

  create table ...(...); 
创建表...(...);

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



所以我想用,因为您可以。但是为了创建一个 SchemaExport 我需要一个 MetadataImplementor (非deprected api)。



我无法弄清楚如何从spring引导中获取 MetadataImplementor



有没有人知道是否存在


  • a javax.persistence.schema-generation 属性定义分隔符

  • 或如何创建 SchemaExport (获取依赖关系)

  • 或有另一种解决方案吗?


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

    @Bean
    public ApplicationRunner getApplicationRunner(){
    返回新的ApplicationRunner(){

    public void run(ApplicationArguments args )抛出异常{
    // MetadataImplementor或metadataImplementor = ???;
    //新建SchemaExport(metadataImplementor);
    }
    };


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

    }

    @实体
    公共类用户{

    @Id
    @GeneratedValue
    私人长ID;

    私人字符串名称;

    public Long getId(){
    return id;
    }

    public String getName(){
    return name;
    }

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

    }

    @Entity
    public class Person {

    @Id
    @GeneratedValue
    私人长ID;

    私人字符串名称;

    public Long getId(){
    return id;
    }

    public String getName(){
    return name;
    }

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

    }

    // application.properties

    spring.jpa.properties.javax.persistence.schema-generation.create -source =元数据
    spring.jpa.properties.javax.persistence.schema-generation.scripts.action =创建
    spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target = create.sql

    // maven dependencies


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

    < dependencyManagement>
    <依赖关系>
    < dependency>
    < groupId> org.springframework.boot< / groupId>
    < artifactId> spring-boot-dependencies< / artifactId>
    < version> $ {spring.boot.version}< / version>
    < type> pom< / type>
    < scope> import< / scope>
    < /依赖关系>
    < /依赖关系>
    < / dependencyManagement>

    <依赖关系>
    < dependency>
    < groupId> org.springframework.boot< / groupId>
    < artifactId> spring-boot-starter-data-jpa< / artifactId>
    < /依赖关系>
    < dependency>
    < groupId> com.h2database< / groupId>
    < artifactId> h2< / artifactId>
    < /依赖关系>
    < /依赖关系>

    使用Hibernate 5.0



    我只是用hibernate 5.0.11.Final 来试过上面的代码。您必须更改的唯一方法是
    $ b $ pre $ code> SchemaExport schemaExport = new SchemaExport((MetadataImplementor)metadata);
    schemaExport.setDelimiter(;);
    schemaExport.setFormat(false);
    schemaExport.setOutputFile(dropAndCreateDdlFile.getAbsolutePath());

    schemaExport.execute(true,false,false,false);

    或者当然让java配置返回一个 MetadataImplementor 代替元数据并更改 ApplicationRunner 构造函数参数。

    解决方案

    最后经过很多调查,我想我找到了一个使用公共API的简单解决方案。我找到的解决方案使用hibernate 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);

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

    元数据元数据= metadataSources.buildMetadata();
    返回元数据; (StandardServiceRegistry.class)
    @Bean
    public StandardServiceRegistry getStandardServiceRegistry(JpaProperties jpaProperties) );

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

    StandardServiceRegistry ssr = ssrb.build();
    返回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();
    返回persistenceUnitInfo;
    }

    }

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

    pre $ @Component
    public class GenerateDDLApplicationRunner实现ApplicationRunner {

    私有元数据元数据;

    public GenerateDDLApplicationRunner(元数据元数据){
    this.metadata = metadata;
    }

    public void run(ApplicationArguments args)throws Exception {
    文件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);
    抛出新的IllegalStateException(msg); $!

    $ b if(!dropAndCreateDdlFile.delete()){
    String msg = MessageFormat.format(Unable to delete file {0},dropAndCreateDdlFile);
    抛出新的IllegalStateException(msg);
    }
    }
    }

    }



    hibernate方言是使用spring boot application.properties 配置的。在我的情况下:

      spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL57InnoDBDialect 


    I want generate create and drop ddl scripts using spring boot v1.4.3 with JPA - Hibernate 5.0.11.

    Most answers I found use the javax.persistence.schema-generation properties. E.g. https://stackoverflow.com/a/36966419/974186

    The problem with this approach is the it outputs the sql statements without an delimiter. E.g.

    create table ... (...)
    create table ... (...)
    

    I want it to output the statements with the delimiter ;

    create table ... (...);
    create table ... (...);
    

    But I can't find any javax.persistence.schema-generation property to configure it.

    So I thought to use the SchemaExport from hibernate, because you can set the delimiter property. But to create a SchemaExport I need a MetadataImplementor (non deprected api).

    I can not figure out how to get a MetadataImplementor from spring boot.

    Does anyone know if there is either

    • a javax.persistence.schema-generation property to define the delimiter
    • or how to create a SchemaExport (get the dependencies)
    • or has another solution?

    Here is some code you can play with

    @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);
        }
    
    }
    
    @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;
        }
    
    }
    
    @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;
        }
    
    }
    
    // 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
    
    // maven dependencies
    
    <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>   
    

    With Hibernate 5.0

    I just tried the code above with hibernate 5.0.11.Final. The only thing you must change is

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

    or of course let the java configuration return a MetadataImplementor instead of Metadata and change the ApplicationRunner constructor param.

    解决方案

    Finally after a lot of investigation I think I found an easy solution that uses public APIs. The solution I found uses hibernate 5.2 (more concrete 5.2.6.Final). But I think it can also be adapted to 5.0

    Here is my spring java configuration

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

    The java configuration creates a Metadata bean. This bean can be used in hibernate 5.2 to execute a schema generation. E.g.

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

    The hibernate dialect is configured using the spring boot application.properties. In my case:

    spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL57InnoDBDialect
    

    这篇关于使用自定义分隔符通过弹簧引导生成DDL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 20:24