Spring Data JPAのEntityクラスからDDLを生成する

プロトタイピングの時はDB周辺の実装を簡略化するため、Spring Data JPA(+Hibernate)を使っています。
プロパティにspring.jpa.hibernate.ddl-auto=create-dropなどを指定すればテーブルを自動で生成できますが、あとで結局DDLが必要になることもあります。
そこで、今回はJPAのEntityクラスを元にDDLを生成する方法を調べました。

JPA Schema Generator Plugin

JPA Schema Generator Pluginというプラグインを見つけたので、これを使います。

Gradle用のプラグインも用意されていますが、今回はMavenを使用します。

JPA Schema Generator Pluginの設定

pom.xmlに以下の設定を記載しました。

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    <plugin>
        <groupId>com.devskiller.jpa2ddl</groupId>
        <artifactId>jpa2ddl-maven-plugin</artifactId>
        <version>0.9.12</version>
        <configuration>
            <outputPath>./schema.sql</outputPath>
            <packages>
                <package>org.tosi29.sample</package>
            </packages>            
            <jpaProperties>
                <property>
                    <name>hibernate.dialect</name>
                    <value>org.hibernate.dialect.MySQL57InnoDBDialect</value>
                </property>
                <property>
                    <name>hibernate.physical_naming_strategy</name>
                    <value>org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy</value>
                </property>
            </jpaProperties>
        </configuration>
    </plugin>
</plugins>

outputPathに生成するDDLのファイルパスを、packageにEntityを含むパッケージ名を指定すればOKです。
プロパティについては多少試行錯誤したので、後述します。

Dialectの指定

プロパティhibernate.dialectにDialectを指定することで、MySQLに限らず様々なDBのDDLを生成することができます。
今回はエンジンにInnoDBを使いたかったので、org.hibernate.dialect.MySQL57InnoDBDialectを指定しました。
Dialectの一覧はここ(Hibernate5.4のユーザーガイド)に記載されています。

ちなみにorg.hibernate.dialect.MySQL5Dialectを使ったらMyISAMになったのですが、最近のorg.hibernate.dialect.MySQL57DialectではInnoDBになるようです。
おそらくMySQLのデフォルトエンジンが変わった影響だと思いますが、指定したほうが確実です。

命名規則の指定

プロパティhibernate.physical_naming_strategyで、テーブル名やカラム名の命名規則を指定できます。
Spring Bootで採用されている命名規則にする場合は org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyを指定します。
これを指定しないと、DDLで生成されるカラム名がスネークケースになりませんでした。
ただし@Table@Columnで明示的に指定していれば、そちらが優先されるようです。

当初、hibernate内を必死に探してもこのクラスを見つけられなかったのですが、SpringBoot側に用意されていたというオチでした…。

JPA Schema Generator Pluginの実行

以下のコマンドを実行すれば生成されます。

mvnw com.devskiller.jpa2ddl:jpa2ddl-maven-plugin:0.9.12:generate

MySQL用のDDLの生成例

今回は以下のEntityクラスを用意して実行しました。

@Entity
@Table(name="my_entities")
public class MyEntity {
	@Id
	private int id;
	private String firstName;
	private String lastName;
	
	@Length(max=20)
	private String max20;
	
	@Column(name="specified")
	private float value;
}

生成されたDDLがこちらです。

create table my_entities (
    id integer not null,
    first_name varchar(255),
    last_name varchar(255),
    max20 varchar(20),
    specified float,
    primary key (id)
) engine=InnoDB;

@Id@Length@Columnなどの指定も適切に反映されているのが分かります。

サンプル

GitHubにアップしました。

所感

Dialectと命名規則にやや苦戦しましたが、容易にDDLを生成できました。
公式の使用方法を見るとFlyway用のマイグレーションスクリプトを自動生成することも可能なようです。
JPAとFlywayを併用する場合には大きく省力化できそうなので、こちらもいずれ試してみたいと思います。

関連記事


  1. Open Session in Viewは使用すべきなのか?
  2. Spring Data JPAのgetOne()で遅延ロードエラー
  3. DDLを自動生成してJavaと各DBのデータ型を比較してみた
  4. JaCoCoでJavaのテストカバレッジのレポートを出力する
  5. MavenでOSSのライセンス一覧を出力する
  6. Spring Boot アノテーション集
  7. データベースを参照してシステム連携する際に気をつけること

comments powered by Disqus