Hibernateを使ったDBアプリ開発ではトップダウンアプローチやボトムアップアプローチなどいくつかの開発アプローチがあります。
これはHibernateで必要なJava Beans、マッピングファイル、テーブル定義のどれか1つでもあれば、他の2つを自動生成できるからですが、データベースエンジニア的にはやはりテーブル定義から始めるのが一番やりやすいでしょう。
ボトムアップアプローチでは、テーブル定義からマッピングファイルを生成し、さらにマッピングファイルからJava Beansを生成します。
テーブル定義からマッピングファイルを生成するにはMiddlegenというツールを使用し、マッピングファイルからJava Beansを生成するにはHibernate Extensionsに含まれるhbm2javaというツールを使用します。
各種ツールのダウンロード
Hibernate、Middlegen、Hibernate Extensionsをダウンロードして任意のディレクトリに解凍します。・Hibernate 2.1.8
・Middlegen 2.1
・Hibernate Extensions 2.1.3
ビルドファイルの準備
マッピングファイルとJavaBeansの生成はAntタスクとして実行します。
ゆえに以下のようなビルドファイルを準備します。
build.xml
<?xml version="1.0" encoding="utf-8"?>
<project name="Hibernate Sample" default="jar" basedir=".">
<target name="init">
<property file="${basedir}/build.properties"/>
<path id="lib.class.path">
<pathelement path="${database.driver.classpath}"/>
<fileset dir="${middlegen.dir}" includes="**/*.jar"/>
<fileset dir="${middlegen.dir}/samples/lib" includes="*.jar"/>
<fileset dir="${hibernate-ext.dir}/tools" includes="**/*.jar"/>
<fileset dir="${hibernate.dir}" includes="**/*.jar"/>
</path>
<taskdef
name="middlegen"
classname="middlegen.MiddlegenTask"
classpathref="lib.class.path"
/>
<taskdef
name="hbm2java"
classname="net.sf.hibernate.tool.hbm2java.Hbm2JavaTask"
classpathref="lib.class.path"
/>
</target>
<target name="db2hbm" depends="init">
<middlegen
appname="${name}"
prefsdir="${build.dir}"
gui="${gui}"
databaseurl="${database.url}"
driver="${database.driver}"
username="${database.userid}"
password="${database.password}"
schema="${database.schema}"
catalog="${database.catalog}"
>
<hibernate
destination="${src.dir}"
package="${package}"
genXDocletTags="${gen.xdoclet-tag}"
javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"
/>
<table name="DEPT"/>
<table name="EMP"/>
</middlegen>
</target>
<target name="hbm2java" depends="db2hbm">
<hbm2java output="${src.dir}">
<fileset dir="${src.dir}">
<include name="**/*.hbm.xml" />
</fileset>
</hbm2java>
</target>
<target name="compile" depends="hbm2java">
<javac destDir="${build.dir}/classes"
srcDir="${build.dir}/classes"
classpathref="lib.class.path" />
<copy todir="${build.dir}/classes">
<fileset dir="${src.dir}">
<include name="**/*.hbm.xml" />
</fileset>
</copy>
</target>
<target name="jar" depends="compile">
<jar destfile="${name}.jar">
<fileset dir="${build.dir}/classes">
<include name="**/*" />
</fileset>
</jar>
</target>
</project>
ここでは"db2hbm"というターゲットでMiddlegenを使ってDEPT表とEMP表のマッピングファイルを生成し、"hbm2java"というターゲットでhbm2javaを使ってマッピングファイルからJavaBeansを生成しています。ビルド時に必要な設定は以下のようにプロパティファイルに設定します。
build.properties
middlegen.dir = c:/java/middlegen-2.1 hibernate.dir = c:/java/hibernate-2.1 hibernate-ext.dir = c:/java/hibernate-extensions-2.1.3 src.dir = src build.dir = build database.driver.classpath = lib/classes12.zip package = scott name = scott database.driver = oracle.jdbc.driver.OracleDriver database.url = jdbc:oracle:thin:@ora-server:1521:ORCL database.userid = SCOTT database.password = TIGER database.schema = SCOTT database.catalog = gui = true gen.xdoclet-tag = true
Antの実行
用意したビルドファイルを指定してAntを実行すると、以下のようなMiddlegenのGUIが表示されます。※※build.propertiesでgui=trueとしている場合
Middlegenではデータベースの定義に基づいて自動的にマッピングを行いますが、このGUIを使えば自動的にマッピングされた内容を必要に応じて変更することができます。
このGUIでマッピングを調整した後、左上の[Generate]ボタンを押せば、マッピングファイルが生成され、さらに右上の[×]ボタンを押してウィンドウを閉じれば、Antの以降のタスクが実行されます。
Middlegen2.1を使うとなぜか"middlegen"のタスクで以下のようなエラーが発生します。
[middlegen] log4j:ERROR Could not find value for key log4j.appender.org.apache.torque.engine [middlegen] log4j:ERROR Could not instantiate appender named "org.apache.torque.engine".
ただし、処理が失敗するわけではないようなので無視しても問題ありません。
マッピングファイルとJavaBeansを自動生成した後は...
Antが終了すると、マッピングファイル(*hbm.xml)、JavaBeans(*.java)が指定したディレクトリに作成されるので、あとは、これらを利用してアプリケーションを作成していけばOKです。ただし、マッピングファイルとJavaBeansは、再度Antを実行すると上書きされてしまうため、これらのファイルに手作業で変更を加えるようなことをするべきではありません。
特にマッピングファイルについては、自動生成した後に調整を行いたいというケースが多いと思われますが、このような場合は、再度Antを実行しMiddlegenのGUI上で調整するのが望ましいでしょう。
MiddlegenのGUI上で調整する箇所が多い場合、毎回同じ調整を行うのは非常に手間が掛かりますが、MiddlegenのGUIで設定したマッピングの設定情報はxxxxx-prefs.propertiesというプロパティファイルにも保存されているため、再度マッピングを行う場合には、前回マッピング時の設定がそのまま利用できます。
逆にデータベース側の定義が変わっているのにそれがマッピングに反映されないということになる場合もあるため注意が必要ですが。