Auto generate data schema from JPA 2.1 annotated entity classes without a database connection

后端 未结 3 1405
清酒与你
清酒与你 2021-01-17 01:09

Two years ago I was working on a project using:

  • spring 4.0.3.RELEASE
  • jpa 2.0
  • hibernate 4.2.7.Final
  • java 1.6.X

This pr

3条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-17 01:40

    As the other question, you can use hbm2ddl and an embedded database to provide a connection.

    For exemple using H2 database (require h2, scannotation, hibernate and common-io):

    package com.stackoverflow;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.InputStream;
    import java.net.URL;
    import java.util.Set;
    import javax.persistence.Entity;
    import org.apache.commons.io.IOUtils;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.cfg.Environment;
    import org.hibernate.connection.DriverManagerConnectionProvider;
    import org.hibernate.dialect.PostgreSQLDialect;
    import org.hibernate.tool.hbm2ddl.SchemaExport;
    import org.scannotation.AnnotationDB;
    
    public class ExportShema {
    
        private static final String OUTPUT_SQL_FILE = "target/database.sql";
        private static final String INIT_FILE = "init.sql";
        private static final String DB_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";
        private static final String DB_USERNAME = "sa";
        private static final String DB_PASSWORD = "";
        private static final File HBM_DIRECTORY = new File("src/main/resources/com/stackoverflow/domain/");
    
        public static void main(final String[] args) throws Exception {
            final Configuration cfg = new Configuration();
            cfg.setProperty(Environment.CONNECTION_PROVIDER, DriverManagerConnectionProvider.class.getName());
            //for postgrest schema
            cfg.setProperty(Environment.DIALECT, PostgreSQLDialect.class.getName());
            cfg.setProperty(Environment.URL, DB_URL);
            cfg.setProperty(Environment.USER, DB_USERNAME);
            cfg.setProperty(Environment.PASS, DB_PASSWORD);
    
            //If you have HBM + annotated class
            cfg.addDirectory(HBM_DIRECTORY);
    
            final AnnotationDB db = new AnnotationDB();
            db.scanArchives(new URL("file:target/classes/"));
            final Set clazzNames = db.getAnnotationIndex().get(Entity.class.getName());
            for (final String clazzName : clazzNames) {
                cfg.addAnnotatedClass(Class.forName(clazzName));
            }
    
            final SchemaExport exporter = new SchemaExport(cfg);
            exporter.setOutputFile(OUTPUT_SQL_FILE);
            exporter.setDelimiter(";");
            exporter.setFormat(true);
            exporter.create(false, true);
    
            try (final InputStream init_file = ExportShema.class.getResourceAsStream(INIT_FILE)) {
                if (init_file != null) {
                    final File output = new File(OUTPUT_SQL_FILE);
                    try (final FileWriter fw = new FileWriter(output, true)) {
                        final String eol = System.getProperty("line.separator");
                        fw.append(eol + eol);
                        fw.append(IOUtils.toString(init_file));
                    }
                }
            }
    }
    }
    

    you can do this in a unit test or create an annotation processor.

提交回复
热议问题