Hibernate+Mavenでドメインモデルからスキーマを自動生成する

O/Rマッパーを使ってデータベースを扱うアプリケーションを作るにも色々なアプローチがあると思いますが、今回はドメインモデル (POJO) をまず作ってからそれを元にデータベースのスキーマを自動的に生成する方法についてです。

hibernate3-maven-plugin

Hibernate にはドメインモデルからスキーマを自動的に生成するツールとして hbm2ddl が用意されています。この hbm2ddl を Maven から実行するプラグインとして hibernate3-maven-plugin があります。

早速ですが pom.xml の設定です。

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>hibernate3-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <verbose>true</verbose>
                    <components>
                        <component>
                            <name>hbm2ddl</name>
                            <implementation>jpaconfiguration</implementation>
                        </component>
                    </components>
                    <componentProperties>
                        <format>true</format>
                        <export>false</export>
                        <outputfilename>schema.ddl</outputfilename>
                    </componentProperties>
                </configuration>
            </plugin>

データベースのアクセスに使う API は implementation タグで指定するようです。今回は JPA (Java Persistence API) を使いました。

ドメインモデルを作る

ありがちですが「人」を表すドメインモデルを作ってみました。

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;

@Entity
public class Person implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    
    @Version
    private Integer version;
    
    private int age;
    
    private String firstname;
    
    private String lastname;

    public Person() {
    }

    public Person(int age, String firstname, String lastname) {
        this.age = age;
        this.firstname = firstname;
        this.lastname = lastname;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
}

JPA を設定する

JPA の設定ファイル (persistence.xml) を以下のように作りました。データベースには MySQL を使う設定です。ドメインモデルは class タグで指定しました。exclude-unlisted-classes タグを使わない場合は明示的にドメインモデルを指定しなくてもパスが通っている場所を自動的に探してくれるみたいです。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="sample">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>test.hibernate.sql.export.domain.Person</class>
        <exclude-unlisted-classes/>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.username" value="****"/>
            <property name="hibernate.connection.password" value="****"/>
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost/test"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.connection.pool_size" value="1"/>
            <property name="hibernate.current_session_context_class" value="thread"/>
            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
            <property name="hibernate.use_outer_join" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

ユーザ名やパスワード、データベース名などは自分の環境に併せて変更してください。あとは HibernateJDBCドライバをパスに依存ライブラリに追加するのも忘れずに。

スキーマを自動生成する

あとは Maven を実行するだけです。

$ mvn clean compile hibernate3:hbm2ddl
…(省略)…
    create table Person (
        id integer not null auto_increment,
        age integer not null,
        firstname varchar(255),
        lastname varchar(255),
        version integer,
        primary key (id)
    );
00:12:03,373  INFO org.hibernate.tool.hbm2ddl.SchemaExport - schema export complete

これで ${project.basedir}/target/hibernate3 ディレクトリに schema.ddl ファイルができているはずです。

pom.xml

念のため、今回使った pom.xml を載せておきます。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>test.hibernate.sql.export</groupId>
    <artifactId>test-hibernate-sql-export</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>test-hibernate-sql-export</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>hibernate3-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <verbose>true</verbose>
                    <components>
                        <component>
                            <name>hbm2ddl</name>
                            <implementation>jpaconfiguration</implementation>
                        </component>
                    </components>
                    <componentProperties>
                        <format>true</format>
                        <export>false</export>
                        <outputfilename>schema.ddl</outputfilename>
                    </componentProperties>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.6.8.Final</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.4</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.18</version>
        </dependency>
    </dependencies>
</project>

まとめ

HibernateMaven を使って、ドメインモデルからスキーマを自動的に生成することができました。Hibernate には hbm2ddl 以外にも、色々と自動化するためのツールが用意されてるみたいです。