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を併用する場合には大きく省力化できそうなので、こちらもいずれ試してみたいと思います。