Hibernate 入門記 Configuration
今日から本格的にHibernateの入門をはじめます.すでにバリバリHibernateを使いこなしている人がチュートリアルを書くのとは違って,大間違いをしたりうろたえたりすると思いますが,それもまた醍醐味の一つということで.(^^;
どのように学習していくか色々迷ったのですが,やはり「Hibernate Reference Documentation」を頼りにしていくことにします.とはいえ,やはり英語より日本語に決まっているので,実際にはozaccさんによる翻訳を読んでいることは言うまでもありません.
というわけで,まずは「Chapter 1. Quickstart with Tomcat」からスタートです.
...
なんでリファレンスの最初がこのテーマ? リファレンスなのに? チュートリアルとして切り出しておけばいいのに.
ここではTomcatに興味ないし,入門寸前で軽く遊んでおいたので,ここはスキップしてしまいましょう.いやその,決して翻訳の方にこの章がないから飛ばすわけではありません,あうあう.
ということで,次は「Chapter 2. Architecture」です.ま,この辺りは字よりも図を見ておけばいいかなぁ,って感じですね.
むむぅ,翻訳(バージョン2.0.x)にあった「1.2. 永続オブジェクトの同一性 (Identity)」が2.1.xからはなくなってるぅ! どこかに移動したんでしょうか?
後はJMXとJCAに対応しているよってことが紹介されていますが,それしか書いてないのでどうでもよさげ.これで2章も終わり♪
そして次は「Chapter 3. SessionFactory Configuration」へと進みます.ここからが本格的な解説の始まりっぽい.
まずは「3.1. Programmatic Configuration」.
Hibernateは,プログラマティックに設定することも,XMLファイルで設定することもできます.そのプログラマティックな設定についての解説です.
Hibernateの諸々の構成は
Configuration
というクラスを用いて設定します.これは,マッピング情報(XMLファイル)も保持します.そのために用意されているメソッドが,
-
Configuration addFile(String)
Configuration addClass(Class)
など.前者はマッピングファイルのパスを引数で渡します.後者は,クラスの完全限定名を元に拡張子 .cfg.xml
をつけたリソースをクラスローダーを使って読み込んでくれるというものです.
他にもディレクトリやJARファイルを渡すと再帰的にマッピングファイルを探してくれるものなど,豊富に用意されています.
面白いことに,これらのメソッドの戻り値は Configuration
自身です.return this;
してるんですね.おかげで
Configuration cfg = new Configuration() .addClass(org.hibernate.auction.Item.class) .addClass(org.hibernate.auction.Bid.class);
みたいに書くことができる,と.Smalltalkではよく見かける書き方ですが,Javaで見るとちょっとドッキリします(StringBuffer
ではよく使いますね).
ちょっと飛ばして先に「3.8. XML Configuration File」へ行っちゃいましょう.
構成をXMLで設定するには,Configuraion
の
-
Configuration configure()
Configuration configure(String)
などを使います.前者のメソッドの場合は,クラスローダーを使って hibernate.cfg.xml
という名前のリソースを探してくれます.後者だとクラスローダーから指定した名前のリソースを探してくれます.
他にもDOMのDocument
を渡すものなどが用意されています.
XMLの書き方については説明されていません.(^^;
例を見れば十分だろ? ってことでしょう.はい,十分だと思います.基本的にプロパティとマッピングファイルの設定だけですからね.
で,ちょっとあちこちに散らばっているConfiguration
に関する情報をここで.
Configuration
はプロパティを持ちます.
まずはクラスローダーから hibernate.properties
というリソースを取得できれば,それを読み込んで設定してくれるみたい.
そしてシステムプロパティの値で上書きされます.
Configuration#configure()
等で使われたXMLに<property>
要素が含まれていれば,そのプロパティが設定されます.
このように設定されたプロパティを変更するには,Configuration
の
-
Configuration setProperties(Properties)
Configuration setProperty(String, String)
などで変更することができます.前者の場合は,以前のプロパティリストを丸ごと置き換えちゃうみたい(追加ではないっぽい).
Configuration
について,現時点ではこれくらいですかね.他にもいろいろメソッドがあるのですが,もっとHibernateのことを理解しないとよく分からないものもあるので.無念だ.
次は「3.2. Obtaining a SessionFactory」です.
Configuration
の準備ができたら
SessionFactory
を取得することができます.そのために使うのがConfiguration
の
-
- buildSessionFactory()
です.SessionFactory
はシングルトンではなく,buildSessionFactory()
は呼び出されるたびに新しいSessionFactory
を作って返すとのこと.SessionFactory
を共有するの仕掛けはアプリケーションで用意しなきゃいけないのですね.だから色々な解説でgetSessionFactory()
とかやっていたわけかぁ.で,そのスマートな解決方法がSpringやS2などのDIConというわけですね.ふむふむ.
どんどん進んで次は「3.3. User provided JDBC connection」と「3.4. Hibernate provided JDBC connection」です.
SessionFactory
を取得すると,そこから
Session
を取得できます.Session
はJDBCコネクションを利用して永続オブジェクトとDBとのやり取りを行ってくれるものです.ということでJDBCコネクションが必要になるのですが,
- Hibernateの外から与えるJDBCコネクションを使う.
- Hibernateが
DriverManager
から取得したJDBCコネクションを使う. - HibernateがJNDI経由の
DataSource
から取得したJDBCコネクションを使う.
といった方法を使うことができます.
最初の場合はSessionFactory
の
-
Session openSession(Connection)
を使います.後の二つはやはりSessionFactory
の
-
Session openSession()
を使います.必要な情報はConfiguration
に設定したプロパティから取得するとのこと.
実際に設定するプロパティの名前や値などは必要に応じてドキュメントを参照するということで.(^^;
だって,DIConを使うとコネクションは外から与えるわけで,あうあう.手抜きじゃないもーん,面倒なだけ〜.一緒か.心より恥じる.
おっと,翻訳(2.0.x)だとなぜかここでSession#beginTransaction()
のことがオプションだとかって書いてあるのですが,2.1.xのドキュメントからは削られていますね.うん,ここでは書かない方がいいと思う.
あと,SessionFactory
はコネクションプールの機能も持っているのですね.DIConとか使う場合は別途コネクションプールを使って,そこから得たコネクションをSessionFactory#openSession(Connection)
に渡すことになると思いますが,ちょっとHibernateだけ使う場合でも手軽にコネクションプールがつかえるのはいいかも.でもそれってどんな場合?
そして「3.5. Optional configuration properties」へ.
すげー,プロパティがたくさんある! いろいろ設定できるらしい.とりあえず重要そうなのは,
hibernate.dialect
- RDBMSの実装の違いを吸収するために使用する
Dialect
実装クラスを指定します.主要なRDBMSに対応した実装クラスが標準で提供されているので,たいていはそれを使うだけでよさげ.でも,国内ベンダのRDBMSは自前でDialect
を用意しなきゃいけないみたい.id:ukki4903さん頑張れ! hibernate.default_schema
- RDBMSのテーブル等を参照する際に修飾するスキーマ名を指定できます.
hibernate.cglib.use_reflection_optimizer
- えぇっ? ここでもCGLIB!? 何に使ってるんだろう? ドキドキ!
hibernate.transaction.factory_class
- トランザクションを制御するためのクラスを指定するらしい.JDBCのトランザクションを使う場合とJTAを使う場合の実装クラスが用意されているらしい.DIConを使う場合はHibernateの外でトランザクションを制御することになると思うので,それほど気にする必要はないように思います.
hibernate.show_sql
true
に設定すると,実行するSQLをロギングしてくれます.
他にもたくさんあるので困ったときは見ることにしよう.
そろそろ疲れた.でも残り少しみたいなので頑張るべし.
「3.6. Logging」によると,ロギングにはLog4JまたはJDK1.4のロギングAPIを使うとのこと.らじゃ.
で,「3.7. Implementing a NamingStrategy」です.
何でも,NamingStrategy
という Interface
が用意されていて,その実装クラスを Configuration#setNamingStrategy(NamingStrategy)
で設定すると,マッピングファイルに記述された「論理的な」テーブル名やカラム名から,「物理的な」名前に自動的に変換してくれるのだそうです.ふーむ.
そういえば,入門寸前にマッピングファイルを作った際,永続オブジェクトのプロパティに対応するDBのカラム名の指定は任意となっていました(プロパティ名と同じカラム名になる).なるほど,例えば firstName
というプロパティに対応するカラム名が FIRST_NAME
なんていう場合にいちいちマッピングファイルに書かなくても,これ一発で済むかもしれないということですか.それはよいかも.
一応,ImprovedNamingStrategy
という実装クラスが用意されていて,これがまさに '_
' を埋め込んでくれる代物らしいです.
ふぅ〜っ,どうにか3章の最後まで到達.ということで実験コーナー!
ここはやっぱり NamingStrategy
でしょう.それしか楽しめるものが見当たりません.
ということで,入門寸前で使ったCostomer
クラスとマッピングファイルはそのままに,テーブルのカラム名を firstname
は first_name
に,lastname
は last_name
に変えてみましょう.
ぐはぁっ,HSQLDBではカラム名を変更できないの!? しょうがないので新しいカラムを追加して値をコピーして古いカラムを削除っと.
そして入門寸前の Main
をそのまま実行!!
Hibernate: select customer0_.id as id, customer0_.firstName as firstName, customer0_.lastName as lastName, customer0_.street as street, customer0_.city as city from customer customer0_ - SQL Error: -28, SQLState: S0022 - Column not found: FIRSTNAME in statement [select customer0_.id as id, customer0_.firstName as firstName, customer0_.lastName as lastName, customer0_.street as street, customer0_.city as city from customer customer0_] - SQL Error: -28, SQLState: S0022 - Column not found: FIRSTNAME in statement [select customer0_.id as id, customer0_.firstName as firstName, customer0_.lastName as lastName, customer0_.street as street, customer0_.city as city from customer customer0_] - Could not execute query java.sql.SQLException: Column not found: FIRSTNAME in statement [select customer0_.id as id, customer0_.firstName as firstName, customer0_.lastName as lastName, customer0_.street as street, customer0_.city as city from customer customer0_] ・ ・ ・
うん,きっちり FIRSTNAME
というカラムが見つからないと吹っ飛んでくれました.
ということで,NamingStrategy
を組み込んでみましょう.
Main
クラスで Configuration
を生成した直後に
config.setNamingStrategy(ImprovedNamingStrategy.INSTANCE);
を追加します(import
文も).
そして再び実行!!
Hibernate: select customer0_.id as id, customer0_.first_name as first_name, customer0_.last_name as last_name, customer0_.street as street, customer0_.city as city from customer customer0_ 0 : Laura Steel, 429 Seventh Av. Dallas 1 : Susanne King, 366 - 20th Ave. Olten 2 : Anne Miller, 20 Upland Pl. Lyon ・ ・ ・
バッチリ!
ということで,3章まで一気に終わりです.やったね! っていうか,あまり面白くなかった気もするのですが(苦笑),しょうがないってことで.
それよりもですね,今回が記念すべき「Hibernate 入門記」の第一回であるような気がするのですが,お試しコーナーのソースやXMLは「入門寸前」に頼っているってどういうこと? 入門寸前って完璧に入門の一部じゃん!
ま,何でも予定通りには進まないということです.心より恥じる.