Hibernate 3.xフィルタの高度な運用


Hibernate 3のフィルタは事前定義でき、クラスと集合層にバインドできます.では、事前定義フィルタとは何でしょうか.「where」句のような制限句を定義できますが、これらの句は相対的なクラスと異なる集合の要素です.これらのフィルタ条件をパラメータ化することができる以外は.また、指定したフィルタを実行して開くべきかどうか、およびフィルタパラメータに入力される値を決定することもできます.
一、いつフィルターを使うか
フィルタの使用理由を説明するために、まず例を見てみましょう.ユーザー情報を管理するWebアプリケーションがあるとします.現在のステータスでは、アプリケーションは同じアプリケーションインタフェースを使用してすべてのユーザー情報を処理します.ただし、エンドユーザーがアクティブユーザーと期限切れユーザーを別々に管理するように要求した場合.これらのステータス情報は、ユーザー・テーブルのカラムに保存されます.このようなニーズに対して、最も容易に考えられる解決策は、各SELECT HQLクエリ文を書き直すことであり、すなわち、各HQLの後にWHERE条件を加えてこれらのデータをフィルタすることである.もちろん、この方法の複雑なプログラムは、あなたのWebプログラムがどのように構築されているかによって異なり、簡単でも複雑でもよい.しかし、簡単でも複雑でも、私たちがテストしたコードを修正しなければなりません.これは私たちのプログラムに非常に大きな危険をもたらします.そしてHibernate 3を用いる.xは、別のソリューションをもたらします.アプリケーションのユーザーステータスにフィルタを作成します.ユーザーがユーザーのステータスを選択した場合(アクティブまたは有効期限切れ)、アプリケーションは現在のHibernateセッションのユーザーステータスフィルタをアクティブにします.これにより、すべてのSELECT HQLクエリはクエリ結果のサブセットを返しますが、Hibernateセッションステータスとユーザーステータスフィルタの両方にコードを追加するだけで、元のコードを変更する必要はありません.
概念的には、WHERE句を使用してアプリケーションでHibernateフィルタと同じ作業を完了することができます.もちろん、データベースにビューを作成して、同じ作業を完了することもできます.(ただし、使用するデータベースはビュー機能をサポートする必要があります).これら3つのソリューションは、いずれも1つ以上のクエリー条件で最終結果を制限できます.Hibernateフィルタの利点は、プログラム内でいつでも閉じるか開くことができることです.つまり、フィルタはプログラム可能であり、フィルタはHibernateのマッピングファイルに定義されているため、メンテナンスが容易になります..もちろん、フィルタにも不足点がありますが、主な不足点は、実行時に新しいフィルタを作成できないことです.プログラムが実行されると、すべてのフィルタがマッピングファイルに指定される必要があります.これにより、フィルタの柔軟性が大幅に制限されますが、フィルタはパラメータ化をサポートします.本明細書の例では、マッピングファイルにユーザ状態情報を保存する列を指定できます.プログラムの実行時に指定できるマッピングファイルで可能なステータス値を指定する必要はありません.次にHibernate 3の使い方を見てみましょう.xのフィルタでプログラムを書きます.
二、フィルターの配置
フィルタを使用するには、まず定義され、応答の要素にバインドされる必要があります.フィルタを定義するには、要素を使用してHibernateフィルタを定義します.次のようになります.
<filter-def name="myFilter">

 <filter-param name="myFilterParam" type="string"/>

</filter-def>

次に、このフィルタをクラスにアタッチします.次のようにします.
<class name="myClass" ...>

 ...

 <filter name="myFilter" condition=":myFilterParam = my_filtered_column"/>

</class>

またはコレクションにアタッチします.
<set ...>

 <filter name="myFilter" condition=":myFilterParam = my_filtered_column"/>

</set>

もちろん、私たちも両方あることができます.
三、フィルターの使い方
新しいフィルタをサポートするために、Hibernate 3.xに新しいインタフェースが追加されました:org.hibernate.Filter、org.hibernate.Sessionにはいくつかの新しい方法が加わった.Sessionでの新しい方法は、enableFilter(String filterName)、getEnabledFilter(String filterName)、disableFilter(String filterName)です.デフォルトでは、フィルタは現在のセッションでオフになっています.これらは、SessionのenableFilter()メソッドを使用してフィルタを明示的に開く必要があります.このメソッドは、新しいフィルタのインスタンスを返します.上記の方法では、次のコードでフィルタを開くことができます.
session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");

ビッグデータセットのフィルタ
Hibernate 3についてx以前のバージョンでは、ビッグデータセットを処理するには大量のコードを使用する必要があります.目的を達成するためには、まずデータセット全体をメモリに装着し、そのデータセットに対してSessionのfilter()メソッドを使用してフィルタリングする必要があります.また、エンティティをフィルタする場合は、すべてのHQLまたはカスタムブロッカーを手動で書く必要があります.
そしてHibernate 3.xでは、データをフィルタリングするためのより簡便で一貫した方法が提供される.Hibernate設計ストリートチームは、国際化されていてもローカルデータであっても、安全のために考えていても、他のことをより効果的な特性で処理したいと考えています.このすべてを説明する例を見てみましょう.
四、実例
1.データのフィルタリング例
「有効なレコード」データベース・モードに従うエンティティがあると仮定します.このエンティティには複数のローがあり、各ローは日付によって異なります.つまり、日付範囲内で有効です.1つのemploymentレコードは、employeesが来たり、行ったり、戻ったりすることができるため、非常に良い例になります.次に、employmentデータの現在のレコードを処理するUI付きプログラムを開発します.新しいフィルタ特性を用いてこの目的を達成するために.まずこのフィルタを定義し、Employeeクラスにアタッチする必要があります.

<filter-def name="effectiveDate">

 <filter-param name="asOfDate" type="date"/>

</filter-def>

<class name="Employee" ...>

 ...

 <many-to-one name="department" column="dept_id" class="Department"/>

 <property name="effectiveStartDate" type="date" column="eff_start_dt"/>

 <property name="effectiveEndDate" type="date" column="eff_end_dt"/>

 ...

 <filter name="effectiveDate" condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>

</class>

<class name="Department" ...>

 ...

 <set name="employees" lazy="true">

<key column="dept_id"/>

<one-to-many class="Employee"/>

<filter name="effectiveDate" condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>

 </set>

</class>


そして、常に現在の有効レコードに加算されることを保証するために.フィルタを簡単に開くだけで、コードは次のとおりです.
Session session = ...;

session.enabledFilter("effectiveDate").setParameter("asOfDate", new Date());

List results = session.createQuery("from Employee as e where e.salary > :targetSalary")

.setLong("targetSalary", new Long(1000000))

.list();

上のHQLでは、salaryの制約条件を1つだけ与えても、フィルタを開発しているため、現在の活動の100万人以上の従業員しか得られません.
2、安全な例
各ユーザーにアクセス権を割り当てるアプリケーションがあるとします.その間、システム内の敏感なエンティティの一部は、アクセス階層に割り当てられます.したがって、1人のユーザーが所属するアクセス層でより多くのものを見ることができるはずです.この例では、アクセス階層のエンティティをフィルタでフィルタします.フィルタを定義します.

<filter-def name="accessLevel">

 <filter-param name="userLevel" type="int"/>

</filter-def>

<class name="Opportunity" ...>

 ...

 <many-to-one name="region" column="region_id" class="Region"/>

 <property name="amount" type="Money">

<column name="amt"/>

<cloumn name="currency"/>

 </property>

 <property name="accessLevel" type="int" column="access_lvl"/>

 ...

 <filter name="accessLevel">= access_lvl]]>

</class>

<class name="Region" ...>

...

<set name="opportunities" lazy="true">

 <key column="region_id"/>

 <one-to-many class="Opportunity"/>

 <filter name="accessLevel">= access_lvl]]>

</set>

...

</class>


次に、フィルタを開きましょう.
User user = ...;

Session session = ...;

session.enableFilter("accessLevel").setParameter("userLevel", user.getAccessLevel());

次のコードは、現在のユーザー・アクセス・レイヤのセットをフィルタリングしてサブセットを得るマウント中の領域です.
Region region = (Region) session.get(Region.class, "EMEA");

region.getOpportunities().size();

四、結論
ここではHibernate 3について簡単に紹介する.xの使用方法について、いくつかの例を示した.これらの例は簡単ですが、Hibernate 3.xフィルタの強さはより深い認識を持っている.上記の例を通して、Webフィルタなどの異なるブロック方法と組み合わせることができれば、より大きな力を発揮することができるかもしれません.