Hibernate は O/R マッピングツールと呼ばれる、リレーショナルデータベースとオブジェクトモデルとの間を埋めるフレームワークです。

リレーショナルデータベースとオブジェクトモデルとのミスマッチには、下記のようなものがあります。

  • オブジェクトの粒度に関する問題
  • サブタイプ(継承)に関する問題
  • オブジェクトの同一性(識別子)に関する問題
  • オブジェクト同士の関連に関する問題
  • オブジェクトの検索に関する問題

Hibernateは、このようなミスマッチを解決する方法を提供します。

リレーショナルシステムにおけるテーブル形式のデータ表現は、オブジェクト指向のJavaアプリケーションで使用されているオブジェクトのネットワークとは根本的に異なっている。この違いが、いわゆるオブジェクト/リレーショナルパラダイムのミスマッチだ。

『Hibernate イン アクション』はじめに より

Hibernateのアーキテクチャ

Hibernateが提供するインターフェースは、大きく分けて4つに分類できます。

  • CRUDとクエリ操作を行うためのインターフェース
  • Hibernateを設定するためのインターフェース
  • イベントをハンドリングするためのコールバックインターフェース
  • マッピング機能を拡張するためのインターフェース

CRUDとクエリ操作を行うためのインターフェース

インターフェース/クラス 説明
Session
  • コネクションとトランザクションの概念を扱うもの
  • Sessionインスタンスの生成と破棄にはコストはかからない
  • 通常、一度のリクエストにつきひとつのSessionを生成する
  • スレッドセーフではない
SessionFactory
  • Sessionインターフェースを返す
  • Sessionと比べ、生成にコストがかかる
  • 通常、アプリケーション全体でひとつのインスタンスを使いまわす
  • データベースひとつにつき、ひとつのSessionFactoryインスタンスを用意する。複数のデータベースを利用する際には、それだけのSessionFactoryインスタンスが必要
  • マッピングファイルを保持する
Transaction
  • トランザクション実装を抽象化する
Query
  • データベースへのクエリ発行を行う
  • クエリはネイティブのSQLかHQLで記述される
  • 生成したSession以外では使えない
Criteria
  • データベースへのクエリをオブジェクト表現を使って生成する

Hibernateを設定するためのインターフェース

Configuration
  • Hibernateのプロパティファイル(デフォルトはhibernate.cfg.xml)を読み込んで、SessionFactoryを生成する

イベントをハンドリングするためのコールバックインターフェース

Lifecycle
  • 永続化オブジェクトが実装する
  • 自身のライフサイクルイベントの通知を受け取ることができる
  • Hibernate特有のインターフェースのため、移植性が低下する
Validation
  • 永続化オブジェクトが実装する
  • 永続化オブジェクトのinsert時、update時に呼び出される
  • Hibernate特有のインターフェースのため、移植性が低下する
Interceptor
  • Hibernate特有のインターフェースだが、永続化オブジェクトには実装せずに、インタセプタ用のクラスに実装する
  • イベントのコールバックを受け取るためには、通常はこのインターフェースを利用する

マッピング機能を拡張するためのインターフェース

UserType
  • ユーザ定義型を実装する場合に利用する
CompositeUserType
  • ユーザ定義型を実装する場合に利用する
拡張ポイント
  • 主キーの生成時(IdentifierGenerator)
  • SQL方言(Dialect)
  • キャッシュ(Cache、CacheProvider)
  • JDBCコネクション管理(ConnectionProvider)
  • トランザクション管理(TransactionFactory、Transaction、TransactionManagerLookup)
  • O/Mマッピング(ClassPersister)
  • プロパティアクセス(PropertyAccessor)
  • プロキシ(ProxyFactory)

バグ?

PostgreSQLでスキーマ指定すると…

環境
  • PostgreSQL8.0.0
  • Hibernate3.1

上記の環境で、PostgreSQLにpublic以外のスキーマでテーブルを作成したときちょっとハマったのでメモ。

現象

  • マッピングファイルにschemaを指定するだけでは、Hibernateで構築されるSQL文にスキーマが記述されない
  • PostgreSQL8.0でスキーマを明示した場合、PostgreSQLがテーブル名・カラム名を小文字に自動変換して解釈する

失敗時にHibernateが構築したSQL文

Hibernate: select max(MESSAGE_ID) from MESSAGE
Caused by: java.sql.SQLException: ERROR: relation "message" does not exist

対策

  • hibernate.cfg.xmlにdefault_schemaを指定する
  • テーブル名・カラム名をダブルクウォート(“”)で囲む

Hibernateの設定ファイルにデフォルトスキーマを指定しなければいけない。また、スキーマ名を指定してSQLを実行すると(例:select * from hibernate.MESSAGE)、PostgreSQLがテーブル名・カラム名を小文字で解釈してしまう。回避するためには、ダブルクウォートで囲む必要がある。

Hibernateのマッピングファイルで、カラム名・テーブル名を「`(バッククウォート)」で囲むことで、SQL文生成時に Hibernate がダブルクウォートを自動で付けてくれます。

Hibernate設定ファイルです。

hibernate.cfg.xml

<hibernate-configuration> 
 <session-factory>     
  <!-- Database connection settings --> 
  <property name="connection.driver_class"> 
   org.postgresql.Driver 
  </property> 
  <property name="connection.url"> 
   jdbc:postgresql://localhost:5432/hibernate_db 
  </property> 
  <property name="connection.username">postgres</property> 
  <property name="connection.password">postgres</property> 
  <property name="default_schema">hibernate</property> 

マッピングファイルです。

マッピングファイル(*.hbm.xml)

<hibernate-mapping> 
  <class name="com.hamasyou.hibernate.hello.Message" 
    schema="hibernate" 
    table="&quot;MESSAGE&quot;"> 
    <id name="id" column="&quot;MESSAGE_ID&quot;"> 
      <generator class="increment"/> 
    </id> 
    <property name="text" column="&quot;MESSAGE_TEXT&quot;"/> 
    <many-to-one  
      name="nextMessage"  
      column="&quot;NEXT_MESSAGE_ID&quot;" 
      cascade="all"/> 
    </class> 
</hibernate-mapping>

&quot;と書いてある部分を「`(バッククウォート)」に変更することで、Hibernate の機能で引用符を付けてくれるようになります。

Hibernateが生成したSQL文

Hibernate: select max("MESSAGE_ID") from hibernate."MESSAGE"
Hibernate: insert into hibernate."MESSAGE" ("MESSAGE_TEXT", "NEXT_MESSAGE_ID", "MESSAGE_ID") values (?, ?, ?)

参考

  • JSF、SpringFramework、Hibernateの3つを同時に学べる良書

  • 薄いながらもよくまとまっています

  • ProシリーズのHibernate本。おそらくかなりの良書だと思われます(読んでない^^;)

  • ProfessionalシリーズのHibernate本。こちらもかなりの良書だと思われます