376 lines
20 KiB
XML
376 lines
20 KiB
XML
<?xml version="1.0" encoding="Shift_JIS"?>
|
||
<chapter id="architecture">
|
||
|
||
<title>アーキテクチャ</title>
|
||
|
||
<sect1 id="architecture-overview" revision="1">
|
||
<title>概観</title>
|
||
|
||
<para>
|
||
Hibernateアーキテクチャの(非常に)高いレベルからのビュー:
|
||
</para>
|
||
|
||
<mediaobject>
|
||
<imageobject role="fo">
|
||
<imagedata fileref="images/overview.svg" format="SVG" align="center"/>
|
||
</imageobject>
|
||
<imageobject role="html">
|
||
<imagedata fileref="../shared/images/overview.gif" format="GIF" align="center"/>
|
||
</imageobject>
|
||
</mediaobject>
|
||
|
||
<para>
|
||
この図はHibernateが、アプリケーションに対して永続化サービス
|
||
(と永続オブジェクト)を提供するために、データベースと設定データを使うことを
|
||
示しています。
|
||
</para>
|
||
|
||
<para>
|
||
ここで実行時アーキテクチャのより詳細なビューをお見せしましょう。
|
||
あいにく、Hibernateは柔軟であり、いろいろなアプローチをサポートしています。
|
||
ここでは、2つの極端な例をお見せします。
|
||
「軽い」アーキテクチャでは、アプリケーションが自前のJDBCコネクションを用意し、
|
||
アプリケーション自身がトランザクションを管理します。
|
||
この方法は、Hibernate APIの最小限のサブセットを使います:
|
||
</para>
|
||
|
||
<mediaobject>
|
||
<imageobject role="fo">
|
||
<imagedata fileref="images/lite.svg" format="SVG" align="center"/>
|
||
</imageobject>
|
||
<imageobject role="html">
|
||
<imagedata fileref="../shared/images/lite.gif" format="GIF" align="center"/>
|
||
</imageobject>
|
||
</mediaobject>
|
||
|
||
<para>
|
||
「重い」アーキテクチャは、アプリケーションから、その下に位置するJDBCやJTAのAPIを
|
||
取り払って抽象化し、その詳細の面倒をHibernateに見させます。
|
||
</para>
|
||
|
||
<mediaobject>
|
||
<imageobject role="fo">
|
||
<imagedata fileref="images/full_cream.svg" format="SVG" align="center"/>
|
||
</imageobject>
|
||
<imageobject role="html">
|
||
<imagedata fileref="../shared/images/full_cream.gif" format="GIF" align="center"/>
|
||
</imageobject>
|
||
</mediaobject>
|
||
|
||
<para>
|
||
以下は、上の図に含まれるオブジェクトの定義です:
|
||
|
||
<variablelist spacing="compact">
|
||
<varlistentry>
|
||
<term>SessionFactory (<literal>org.hibernate.SessionFactory</literal>)</term>
|
||
<listitem>
|
||
<para>
|
||
1つのデータベースに対するコンパイルされたマッピングの
|
||
スレッドセーフな(更新不能の)キャッシュ。
|
||
<literal>Session</literal> のファクトリであり、
|
||
<literal>ConnectionProvider</literal> のクライアント。
|
||
オプションとして、プロセスまたはクラスタレベルにおいて、
|
||
トランザクション間で再利用可能なデータの(二次)キャッシュを持ちます。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>Session (<literal>org.hibernate.Session</literal>)</term>
|
||
<listitem>
|
||
<para>
|
||
アプリケーションと永続ストアとの対話を表す、
|
||
シングルスレッドで短命のオブジェクト。
|
||
JDBCコネクションをラップします。
|
||
<literal>Transaction</literal> のファクトリです。
|
||
永続オブジェクトの必須の(一次)キャッシュを保持します。
|
||
このキャッシュはオブジェクトグラフをナビゲーションする時や、
|
||
識別子でオブジェクトを検索する時に使われます。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>Persistent objects と Collections</term>
|
||
<listitem>
|
||
<para>
|
||
永続化状態とビジネスメソッドを持つ、短命でシングルスレッドのオブジェクト。
|
||
これは通常のJavaBeans/POJOのこともありますが、特徴的なことは、
|
||
その時点での(ただ1つの) <literal>Session</literal> と関連していることです。
|
||
<literal>Session</literal> がクローズされるとすぐに、
|
||
それらは切り離されて他のアプリケーション層から自由に使うことができます。
|
||
(例えばデータ・トランスファ・オブジェクトとして、
|
||
プレゼンテーション層から、またはプレゼンテーション層へ直接使用できます。)
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>Transient と detached な objects と Collections</term>
|
||
<listitem>
|
||
<para>
|
||
現時点では <literal>Session</literal> と関連していない、
|
||
永続クラスのインスタンス。
|
||
すでにアプリケーション側でインスタンス化されていて、まだ永続化されていないか、
|
||
クローズされた <literal>Session</literal> でインスタンス化されたかのどちらかです。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>Transaction (<literal>org.hibernate.Transaction</literal>)</term>
|
||
<listitem>
|
||
<para>
|
||
(オプション)原子性を持つ作業単位(Unit of Work)を指定するために、アプリケーションが使用する、
|
||
シングルスレッドで短命なオブジェクト。
|
||
下に位置するJDBC、JTA、CORBAトランザクションからアプリケーションを抽象化します。
|
||
<literal>Session</literal> は、時には
|
||
いくつかの <literal>Transaction</literal> をまたがるかもしれません。
|
||
しかし、下の層のAPIを使うにせよ、 <literal>Transaction</literal> を使うにせよ、
|
||
トランザクション境界を設定することは、決してオプションではありません!。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>ConnectionProvider (<literal>org.hibernate.connection.ConnectionProvider</literal>)</term>
|
||
<listitem>
|
||
<para>
|
||
(オプション)JDBCコネクション(とそのプール)のファクトリ。
|
||
下の層に位置する <literal>Datasource</literal> や
|
||
<literal>DriverManager</literal> からアプリケーションを抽象化します。
|
||
アプリケーションには公開されませんが、開発者が継承または実装することは可能です。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>TransactionFactory (<literal>org.hibernate.TransactionFactory</literal>)</term>
|
||
<listitem>
|
||
<para>
|
||
(オプション) <literal>Transaction</literal> インスタンスのファクトリ。
|
||
アプリケーションには公開されませんが、開発者が継承または実装することは可能です。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>Extension Interfaces</emphasis></term>
|
||
<listitem>
|
||
<para>
|
||
Hibernateは、永続層の振る舞いをカスタマイズするために、
|
||
多くのオプション拡張インタフェースを用意しています。
|
||
詳細はAPIドキュメントを参照してください。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</para>
|
||
|
||
<para>
|
||
「軽い」アーキテクチャでは、アプリケーションは直接JTAやJDBCと対話するために、
|
||
<literal>Transaction</literal> や <literal>TransactionFactory</literal> や
|
||
<literal>ConnectionProvider</literal> をバイパスします。
|
||
</para>
|
||
</sect1>
|
||
|
||
<sect1 id="architecture-states" revision="1">
|
||
<title>インスタンスの状態</title>
|
||
<para>
|
||
永続クラスのインスタンスは、次の3つの異なる状態のどれかになります。
|
||
それは、 <emphasis>永続コンテキスト</emphasis> によって決まります。
|
||
Hibernateの <literal>Session</literal> オブジェクトが、永続コンテキストになります。
|
||
</para>
|
||
|
||
<variablelist spacing="compact">
|
||
<varlistentry>
|
||
<term>transient</term>
|
||
<listitem>
|
||
<para>
|
||
この状態のインスタンスは、現在もそして過去においても、
|
||
永続コンテキストに関連づいていません。また、永続ID(主キーの値)を
|
||
持っていません。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>persistent</term>
|
||
<listitem>
|
||
<para>
|
||
この状態のインスタンスは、その時点で永続コンテキストに関連づいています。
|
||
また、永続ID(主キーの値)を持ち、
|
||
たいていはデータベースに対応する行を持っているでしょう。
|
||
個々の永続コンテキストのなかでは、永続IDが
|
||
JavaのID(オブジェクトのメモリ上の位置)と同じであることを
|
||
Hibernateが <emphasis>保証</emphasis> します。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>detached</term>
|
||
<listitem>
|
||
<para>
|
||
この状態のインスタンスは、かつて永続コンテキストに関連づけられたが、
|
||
そのコンテキストがクローズされたか、あるいは、
|
||
他のプロセスにそのインスタンスがシリアライズされたかです。
|
||
このインスタンスは、永続IDを持ち、たいていはデータベースに
|
||
対応する行を持っているでしょう。分離インスタンスに対しては、
|
||
永続IDとJavaのIDとの関連は、Hibernateが保証しません。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</sect1>
|
||
|
||
<sect1 id="architecture-jmx" revision="1">
|
||
<title>JMXとの統合</title>
|
||
|
||
<para>
|
||
JMXはJavaコンポーネント管理のJ2EE標準です。
|
||
JMX標準サービスを通して、Hibernateは管理されます。
|
||
ディストリビューションの中に <literal>org.hibernate.jmx.HibernateService</literal> という
|
||
MBean実装を用意しています。
|
||
</para>
|
||
|
||
<para>
|
||
JBoss アプリケーションサーバー上にHibernateをJMXサービスとしてデプロイする方法の例としては、
|
||
JBoss ユーザガイドを参照してください。 JBoss アプリケーションサーバーにおいて、
|
||
JMXを使ってデプロイすると、次のメリットが得られます。
|
||
</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>
|
||
<emphasis>セッション管理:</emphasis> Hibernateの <literal>Session</literal> のライフサイクルは、
|
||
自動的にJTAトランザクションのスコープに結びつけられます。これは、もはや手動で
|
||
<literal>Session</literal> をオープンしたり、クローズしたりする必要がないことを意味します。
|
||
これは、JBoss EJB インターセプタの仕事になります。
|
||
また、コードのどこでトランザクション境界を設定するかについて、
|
||
もはや悩む必要がありません(もちろん移植可能な永続層を書かかなくていいのならば、
|
||
オプションのHibernateの <literal>Transaction</literal> を使用してください。)
|
||
<literal>Session</literal> にアクセスするためには、 <literal>HibernateContext</literal> を
|
||
コールしてください。
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<emphasis>HAR デプロイ:</emphasis> 通常、(EAR または SAR ファイルにある)JBoss サービス
|
||
デプロイメントディスクリプタを使って、Hibernate JMX サービスをデプロイします。
|
||
それは、Hibernateの <literal>SessionFactory</literal> の全ての一般的な設定オプションを
|
||
サポートします。しかし依然としてデプロイメントディスクリプタのなかにすべてのマッピングファイルの
|
||
名前を挙げる必要があります。
|
||
もし、オプションのHARデプロイメントを使うことを決めたなら、
|
||
JBossは自動的にHARファイルのなかの全てのマッピングファイルを検出します。
|
||
</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>
|
||
これらのオプションについての詳細な情報は、JBossアプリケーションサーバユーザガイドを
|
||
参考にしてください。
|
||
</para>
|
||
|
||
<para>
|
||
JMXサービスとして利用可能な他の機能に、Hibernate実行時統計情報があります。
|
||
<xref linkend="configuration-optional-statistics"/> を見てください。
|
||
</para>
|
||
</sect1>
|
||
|
||
<sect1 id="architecture-jca" revision="1">
|
||
<title>JCA サポート</title>
|
||
<para>
|
||
Hibernate は JCA コネクタとしても設定できます。詳細については、Webサイトを見てください。
|
||
Hibernate JCA サポートは、今のところ実験段階として考えられていることに注意してください。
|
||
</para>
|
||
</sect1>
|
||
|
||
<sect1 id="architecture-current-session" revision="2">
|
||
<title>コンテキスト上のセッション</title>
|
||
<para>
|
||
Hibernate を使ったアプリケーションは、ほとんど、なんらかの形で"コンテキスト上の"セッションが必要になります。
|
||
「コンテキスト上のセッション」は、特定のコンテキストのスコープのなかで有効なセッションのことです。
|
||
しかし、通常アプリケーションごとにコンテキストを構成するものの定義は異なります。
|
||
しかも、異なる複数のコンテキストは、現時点に対して異なるスコープを定義します。
|
||
バージョン3.0より前の Hibernate では、自作の <literal>ThreadLocal</literal> ベースの「コンテキスト上のセッション」を
|
||
利用するか、 <literal>HibernateUtil</literal> のようなヘルパークラスを利用するか、
|
||
proxy/interception ベースの「コンテキスト上のセッション」を提供する
|
||
(Spring や Pico のような)サードパーティのフレームワークを利用するかのいずれかでした。
|
||
</para>
|
||
|
||
<para>
|
||
バージョン 3.0.1 から、Hibernate には <literal>SessionFactory.getCurrentSession()</literal> が
|
||
加わりました。 これは、 <literal>JTA</literal> トランザクションの使用を前提にしています。
|
||
<literal>JTA</literal> トランザクションは、現在のセッションのスコープとコンテキストの両方を定義します。
|
||
Hibernate チームは、次のことを主張します。
|
||
巨大なスタンドアロンの <literal>JTA TransactionManager</literal> 実装が成熟したら、
|
||
<literal>J2EE</literal> コンテナ上にデプロイされるかどうかにかかわらず、
|
||
ほとんどの(すべてとは言わないが)アプリケーションが、
|
||
<literal>JTA</literal> トランザクション管理を使用すべきであると。
|
||
この考えに基づくと、 <literal>JTA</literal> ベースの「コンテキスト上のセッション」を
|
||
使うしかないでしょう。
|
||
</para>
|
||
|
||
<para>
|
||
しかし、バージョン 3.1 からは、 <literal>SessionFactory.getCurrentSession()</literal> の後の処理が、
|
||
プラガブルになりました。
|
||
これを受けて、現在のセッションを定義するスコープとコンテキストのプラガビリティを可能にするために、
|
||
新しい拡張インタフェース ( <literal>org.hibernate.context.CurrentSessionContext</literal> ) と
|
||
新しい構成パラメータ ( <literal>hibernate.current_session_context_class</literal> ) が追加されました。
|
||
</para>
|
||
|
||
<para>
|
||
<literal>org.hibernate.context.CurrentSessionContext</literal> インタフェースの規約についての
|
||
詳細な内容は Javadoc を参照してください。
|
||
それには、 <literal>currentSession()</literal> という1つのメソッドが定義されており、
|
||
その実装は、現在の「コンテキスト上のセッション」を追跡することに責任を持ちます。
|
||
そのまま使えるように、Hibernateはこのインタフェースの実装を2つ提供しています。
|
||
</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>
|
||
<literal>org.hibernate.context.JTASessionContext</literal> -
|
||
<literal>JTA</literal> トランザクションによって、現在のセッションが追跡され、
|
||
スコープを決められます。この処理は、古いJTAだけのアプローチとまったく同じです。
|
||
詳細はJavadocを参照してください。
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<literal>org.hibernate.context.ThreadLocalSessionContext</literal> -
|
||
スレッドの実行によって、現在のセッションが追跡されます。
|
||
詳細はJavadocを参照してください。
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<literal>org.hibernate.context.ManagedSessionContext</literal> -
|
||
スレッドの実行によって、現在のセッションが追跡されます。
|
||
しかし、このクラスのstaticメソッドで <literal>Session</literal> インスタンスを
|
||
バインド/アンバインドする責任はあなたにあります。
|
||
これは決して <literal>Session</literal> をオープン、フラッシュ、クローズしません。
|
||
</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>
|
||
始めの2つの実装は、"1セッション - 1データベーストランザクション" プログラミングモデルを提供します。
|
||
これは <emphasis>リクエストごとのセッション(session-per-request)</emphasis> としても知られており、使われています。
|
||
Hibernate セッションの開始と終了は、データベーストランザクションの期間で決まります。
|
||
JTAを使わない普通のJSEで、プログラム上のトランザクション境界設定を行うなら、
|
||
コードから基礎のトランザクションシステムを隠蔽するために、
|
||
Hibernate <literal>Transaction</literal> APIを使うとよいでしょう。
|
||
JTAを使うなら、トランザクションの境界設定には、JTAインターフェイスを使ってください。
|
||
CMTをサポートするEJBコンテナで実行するつもりなら、トランザクション境界は宣言的に定義できるため、
|
||
コード上でトランザクションやセッションの境界を設定する必要はありません。
|
||
さらに詳細な情報やコードの例は、 <xref linkend="transactions"/> を参照してください。
|
||
</para>
|
||
|
||
<para>
|
||
<literal>hibernate.current_session_context_class</literal> 設定パラメータは、
|
||
<literal>org.hibernate.context.CurrentSessionContext</literal> のどの実装を使うかを指定します。
|
||
下位互換性のため、このパラメータが設定されず
|
||
<literal>org.hibernate.transaction.TransactionManagerLookup</literal> が設定されていた場合、
|
||
Hibernateは <literal>org.hibernate.context.JTASessionContext</literal> を使うことに注意してください。
|
||
通常このパラメータの値には、3つの実装の中から使用する実装クラスの名前を直接指定します。
|
||
しかし、"jta", "thread", "managed"というそれぞれの省略名も用意されています。
|
||
</para>
|
||
|
||
</sect1>
|
||
|
||
</chapter>
|
||
|