ファイヤープロジェクト
Hibernate入門(Hibernate3)
2005-04-02T17:30+09:00   matsu
挿入,選択,更新,削除を行う単純なサンプルを作成し,Hibernateの概要を掴んでみる.
HibernateはO/Rマッピングツールと呼ばれ,設定ファイルに記述した内容によって,RDBとJavaオブジェクトのマッピングを行う. Javaオブジェクトは自作する必要があるが(※),それをRDBに格納するための仕組み(SQL生成も含む)はO/Rマッピング情報によりHibernateが自動的に行ってくれる. 生成するSQLは上質で,本家はHigh Performanceを自認している.
※ Hibernate2ではhbm2javaという,設定ファイルからJavaコードを生成するツールがあるが,Hibernate3にはまだ見当たらない.
基本を押えつつ最も簡単であることを目指したサンプルを作成した. これ. サンプルの実行方法は以下.
$ tar zxvf HelloHibernate-0_01.tar.gz 
$ ant init
$ ant preparelib
DB構築
conf/create_table.sqlを使用してテーブル作成
filter.propertiesを編集(FILL MEと書いてある部分)
$ ant run
ant preparelibではhttpでhibernate3とポスグレ用JDBCドライバをダウンロードし,展開するが,httpプロキシに対応していない. つまりうまくダウンロードできない場合はWebブラウザなどから以下をダウンロードする. また,ポスグレ以外のDBを使用する場合別途自力でJDBCドライバを用意されたい. ant runすると,DBアクセスしてレコードの追加,選択,更新,削除をして終了しているようなログが出る. 詳細は後述.
上記サンプルのようなHibernateを使用してDBアクセスを行うJavaアプリケーションを開発する場合,以下のような作業が必要であった.
hibernate.cfg.xmlファイルの作成
Hibernateの最も基本的な設定を記述する設定ファイル. HibernateがDBにアクセスする際に使用するDBの情報や,下記hbm.xmlファイルの指定を記述する.
hbm.xmlファイルの作成
O/Rマッピングを記述したファイル
POJO(Plain Old Java Object)クラスの作成
POJOは文字通り「普通の」Javaクラスのオブジェクトである. hbm.xmlファイルで指定したクラス,フィールド,フィールドに対するsetter,getterをもつ.
DBアクセスのコーディング
Hibernateで提供されている仕組みを利用して,DBのデータからオブジェクトを生成したり,オブジェクトデータをDBに格納,更新したり,削除したりする.
当然,DBアクセスとは直接関係ない部分をコーディングする必要もある. 以降,各作業の詳細について記述していく.
サンプルのhibernate.cfg.xmlを以下に示す.
上記ではルート要素hibernate-configurationは一つのsession-factory要素をもつ. これはDBとのセッションを作成する際の設定を表し,子要素にて以下の設定をしている.
show_sql
発行するSQLをログ出力するか否か.
dialect
SQLのDB依存部分を隠蔽するための設定. サンプルはPostgreSQLを想定しているのでorg.hibernate.dialect.PostgreSQLDialectとした.
hibernate.connection.driver_class
JDBCドライバクラス.
hibernate.connection.url
DB接続時のURL.
hibernate.connection.username
DB接続時のユーザ名.
hibernate.connection.password
DB接続時のパスワード.
mapping
O/Rマッピング設定ファイルのパス. 設定ファイルの内容については次節にて記述する.
上記設定によって,HibernateがDBに接続可能となり,またO/Rマッピング情報の取得場所も分かる. hibernate.cfg.xmlはクラスパス上に置く.
hibernate.cfg.xmlの要素mappingで記述したように,サンプルのO/RマッピングファイルはSimpleMessage.hbm.xmlである. どうやらファイル名は
Javaクラス名.hbm.xml
のようなスタイルにする慣習のようだ. サンプルのSimpleMessage.hbm.xmlを以下に示す.
このマッピングファイルでO/RマッピングしているR側すなわちDBのテーブルは以下である.
CREATE TABLE simplemessage(
  id INTEGER PRIMARY KEY,
  message TEXT NOT NULL
);
これを踏まえてマッピングファイルを見てみる. まずルート要素はhibernate-mappingである. 次に上記テーブルsimplemessageをオブジェクトにマッピングする際のクラス名を記述.
        <class name="SimpleMessage"
この子要素に二つの属性id,messageについての記述を行っている.
id
キーは要素idで記述する. 子要素にgeneratorがある. これによっていちいち設定しなくても,idが自動採番される. 属性nameが指定されると,id値をマッピングするJavクラスのgetterで取得できる. 属性nameが指定されないと,id値はSession#getIdentifier()でないと取得できない.
message
キーではないので,要素propertyで指定する. 属性nameの値はマッピングするJavaクラスのsetterとgetterに使用する. 子要素のcolumnはDBテーブル上の属性の名前である.
O/Rマッピング設定ファイルでは他にもいろんな設定ができるが,それは別途機会があれば記述する. このO/Rマッピングにしたがって記述したJavaクラスファイルを以下に示す.
DBとマッピングしている属性のsetter,getterが合致しているかどうかに注意する.
HibernateにDBとJavaオブジェクトのマッピングをまかせるための準備ができたので,後は使用するだけである.
サンプルでは以下を行っている.
  1. オブジェクトを生成してHibernateを使用してそれを格納.
  2. 格納したオブジェクトのいくつかを読み込み.
  3. 読み込んだオブジェクトの属性を更新,DBへ反映.
  4. 格納したオブジェクトのいくつかを読み込み.
  5. 読み込んだオブジェクトをDBから削除.
  6. 全レコードを削除.
ポイントを以下に示す.
hibernate.cfg.xmlの読み込み
hibernate.cfg.xmlには要素session-factoryがあり,これを使用してDBへのSessionを生成してくれるSessionFactoryオブジェクトを生成する.
	SessionFactory sessionFactory =
            new Configuration().configure().buildSessionFactory();
hibernate.cfg.xmlにはマッピング設定ファイルが記述されたりしているので,それらも裏で読み込まれる. 注意点はSessionFactoryオブジェクトは1つのhibernate.cfg.xmlに対して一つとなるようにする点である. 複数のDBへの接続を可能とするために,SessionFactoryにはSingletonパターンが適用されていないので,ユーザが注意してコーディングする必要がある.
トランザクション
SessionFacotryオブジェクトからSessionオブジェクトを取得し,Sessionオブジェクトに対してトランザクションの開始を指定する. このときTransactionオブジェクトを取得できる.
	Session session = sessionFactory.openSession();
	Transaction transaction= session.beginTransaction();
トランザクション終了時にはTransactionオブジェクトに対してcommitを発行する. 失敗した場合はrollback()もある. Sessionのクローズも忘れずに行う.
	transaction.commit();
	session.close();
オブジェクトのDBへの格納
SessionオブジェクトにO/Rマッピングの設定があるオブジェクトと渡すSQLが発行され,O/Rマッピングに基づいてDBにデータが格納される.
	    SimpleMessage simpleMessage = new SimpleMessage();
	    simpleMessage.setMessage("hello" + i);
	    // DBに格納
	    session.save(simpleMessage);
オブジェクトをDBから復元
O/Rマッピングに基づいて,DBのデータからオブジェクトを復元(生成)するには,HQL(Hibernate Query Languqge)あるいはSQLを使用してレコードを特定するための条件を記述する. サンプルではHQLを使用した.
	Query query = session.createQuery("from SimpleMessage as msg where msg.id / 3 = ?");
	query.setInteger(0, 10);
 	List result = query.list();
上のサンプルではJDBCでいうpreparestatemantのようなことをして,次に値を設定し,最後のquery.list()によってSQLが発行している.
DBレコードの更新
JavaアプリケーションにてO/Rマッピングしているオブジェクトのメンバを更新した場合,Session#update(Object)によって更新できる.
DBレコードの削除
Session#delete(Object)によって削除できる.
任意のクエリの発行
上記ではJavaアプリケーション側でO/Rマッピングしているオブジェクトを取得している,あるいは取得する場合の処理だった. 手もとにそういったオブジェクトがない(あるいは必要ない)場合の処理も可能である. 例えば全レコードを削除する場合,Hibernate呼び出しにO/Rマッピングしているオブジェクトは必要なく,返却値にもそれはない.
	Query query = session.createQuery("delete from SimpleMessage");
	int result = query.executeUpdate();
	logger.info("all delete result = " + result);
Session#createQuery(String)にて任意のHQLを指定し,JDBCOと同様,executeUpdate()にてSQLを発行している.
matsu(C)
Since 2002
Mail to matsu