Computer

HibernateでJPAエンティティをスキャンしてスキーマを作成する方法

2020年3月7日

概要

先日、JPA Entityクラスをスキャンしてスキーマを生成・削除するコードを書く必要があったので、そのコードをまとておこうと思います。

コードを作成したのは以下の環境です。

  • Java 8
  • JPAのプロバイダはHibernate

依存関係

まずは、必要なライブラリを追加します。

        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.11</version>
        </dependency>

このライブラリを使って、@Entity アノテーションが付いたクラスをスキャンしています。

Javaコード

次は実際のコードです。

@SpringBootApplication
public class TestApplication {

    private static final Logger logger = LoggerFactory.getLogger(TestApplication.class);

    @PostConstruct
    private void init() throws IOException {

        Files.deleteIfExists(Paths.get("target/create-schema.sql"));

        SchemaExport schemaExport = buildSchemaExport();
        schemaExport.setHaltOnError(true);
        schemaExport.setFormat(true);
        schemaExport.setDelimiter(";");
        schemaExport.setOutputFile("target/create-schema.sql");
        schemaExport.execute(true, true, false, true);
    }

    @PreDestroy
    private void destroy() throws IOException {

        Files.deleteIfExists(Paths.get("target/drop-schema.sql"));

        SchemaExport schemaExport = buildSchemaExport();
        schemaExport.setHaltOnError(true);
        schemaExport.setFormat(true);
        schemaExport.setDelimiter(";");
        schemaExport.setOutputFile("target/drop-schema.sql");
        schemaExport.execute(true, true, true, false);
    }

    private SchemaExport buildSchemaExport() {
        Map<String, String> settings = new HashMap<>();
        settings.put("connection.driver_class", "org.h2.Driver");
        settings.put("dialect", "org.hibernate.dialect.H2Dialect");
        settings.put("hibernate.connection.url", "jdbc:h2:mem:test");
        settings.put("hibernate.connection.username", "sa");
        settings.put("hibernate.connection.password", "");
        settings.put("hibernate.hbm2ddl.auto", "create");
        settings.put("show_sql", "true");

        MetadataSources metadata = new MetadataSources(
                new StandardServiceRegistryBuilder()
                        .applySettings(settings)
                        .build());

        new Reflections("package.to.scan").getTypesAnnotatedWith(Entity.class).forEach(entity -> {
            logger.info("Found entity: {}", entity.getName());
            metadata.addAnnotatedClass(entity);
        });

        SchemaExport schemaExport = new SchemaExport(
                (MetadataImplementor) metadata.buildMetadata()
        );
        return schemaExport;
    }

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

スキーマ作成も削除もコードはほとんど変わりません。違うところといえば、SchemaExport#export メソッドの3番目と4番目のパラメータだけです。executeメソッドのシグニチャは以下のようになっています。

public void execute(boolean script, boolean export, boolean justDrop, boolean justCreate) { /* compiled code */ }

3番目の引数はjustDropとなっていますので、ここをtrueにすればスキーマが削除されます。4番目はjustCreateなので、生成するときにはtrueにします。

// Create schema
schemaExport.execute(true, true, false, true);
// Delete schema
schemaExport.execute(true, true, true, false);

上のサンプルではSpring Bootを使ってコンテナの起動時と終了時にスキーマの生成と削除を行っていますが、Springを使わなくても任意のタイミングでメソッドを呼び出すこともできます。

-Computer

Copyright© dawaan , 2020 All Rights Reserved.