8.NHibernate編
これまで、主にRDBMSを対象にしたDBアクセスについて解説を行いましたが、NHibernateはRDBMSではありません。NHibernateはオブジェクト関係(O/R)マッピングフレームワークと言われるもので、言い換えれば、NHibernateを経由したDBアクセスについて解説を行う、ということになります。
Wikipediaでは、オブジェクト関係マッピングについて
データベースとオブジェクト指向プログラミング言語の間の非互換なデータを変換するプログラミング技法である。と解説しています。もう少し簡単に言うとしたら、RDBへのアクセスをあたかもdb4oのようなODBへのアクセスのように行う方法、でしょうか。
NHibernateではマッピング先のRDB上のテーブルへのデータ登録を次の様なコードで実現しています。
Configuration cfg = new Configuration(); cfg.Configure(); ISessionFactory factory = cfg.BuildSessionFactory(); ISession session = factory.OpenSession(); Product product = new Product{ Id = 1, Name = "Clamp", Price = 12.48M, Description = "Workbench clamp" }; session.Save(product);また、登録したデータの検索は
var result = session.Get<Product>(1);で可能です。
NHibernateは複数のRDBMSをサポートし、これまでの記事で使用したすべてのRDBMSで使用可能です。本稿では、NHibernateを使用した、RDBMSへのDBアクセスについて解説を行います。NHibernateについてはWikipediaなどを参照して下さい。
セットアップ
NHibernateの動作に必要なアセンブリの導入を行います。各RDBMSのセットアップについては、これまでの記事を参照して下さい。ただ、本稿での動作環境は、以前と異なる部分があるので、セットアップ上の変更点については、「おまけ」の節で解説します。アセンブリの導入
NHibernateはSourceForgeのNHibernateプロジェクトページからダウンロード可能です。現時点(2009.09.02)の最新版は2.1.0.GAです(NHibernate 2.1.0はHibernate 3.2.6に相当)。「NHibernate-2.1.0.GA-bin.zip」を任意のディレクトリで展開し、次のアセンブリをGACへインストールまたは環境変数MONO_PATHに設定されているディレクトリへコピーします。
[必要なアセンブリ]
アセンブリ | 概要 |
---|---|
NHibernate.dll | NHibernate Service Provider |
Iesi.Collections.dll | required from NHibernate |
log4net.dll | required from NHibernate |
NHibernate.ByteCode.LinFu.dl | need for proxyfactory.factory_class |
LinFu.DynamicProxy.dll | need for proxyfactory.factory_class |
[導入例(MONO_PATH)]
$ echo $MONO_PATH
/home/sta/lib
$ unzip NHibernate-2.1.0.GA-bin.zip -d NHibernate-2.1.0.GA-bin/
$ cd NHibernate-2.1.0.GA-bin/Required_Bins
$ cp *.dll ~/lib
$ cd ../Required_For_LazyLoading/LinFu
$ cp *.dll ~/lib
/home/sta/lib
$ unzip NHibernate-2.1.0.GA-bin.zip -d NHibernate-2.1.0.GA-bin/
$ cd NHibernate-2.1.0.GA-bin/Required_Bins
$ cp *.dll ~/lib
$ cd ../Required_For_LazyLoading/LinFu
$ cp *.dll ~/lib
コンフィグファイル
RDBMSへの接続情報等を設定します。「NHibernate-2.1.0.GA-bin.zip」には、各RDBMS用NHibernateコンフィグファイルのテンプレートが含まれています(「展開先/Configuration_Templates」配下)。それらを参考にして、各RDBMS用のコンフィグファイルを用意します(以下は、SQLiteを対象にした設定例になります)。作業する上でのディレクトリ構造は、下表の通りとします。
ディレクトリ | ファイル |
---|---|
~/src/cs/NHibernateExample/Driver | MonoDataSqliteDriver.cs |
~/src/cs/NHibernateExample/Test | SQLite.cfg.xml |
[NHibernateコンフィグファイル例(SQLite.cfg.xml:SQLite用)]
<?xml version="1.0" encoding="utf-8" ?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <session-factory name="NHibernateExample"> <property name="connection.driver_class">NHibernateExample.Driver.MonoDataSqliteDriver, NHibernateExample</property> <property name="connection.connection_string">Data Source=/home/sta/data/sqlite/TestData.db</property> <property name="show_sql">false</property> <property name="dialect">NHibernate.Dialect.SQLiteDialect</property> <property name="query.substitutions">true=1;false=0</property> <property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property> <mapping file="Product.hbm.xml" /> </session-factory> </hibernate-configuration>コンフィグファイルの読み込みは、
Configuration cfg = new Configuration(); cfg.Configure();とした場合、実行プログラムと同じディレクトリにある「hibernate.cfg.xml」が読み込まれ、
cfg.Configure("SQLite.cfg.xml");とした場合、同じディレクトリにある任意のファイル「SQLite.cfg.xml」が読み込まれます。
SQLite用コンフィグファイルのテンプレートでは、SQLite用データプロバイダを使用するためのドライバとして、「NHibernate.Driver.SQLiteDriver」が設定されていますが、同ドライバで呼び出しているのは「SQLite.NET」であり、Monoで標準提供されている「Mono.Data.Sqlite」ではありません。ということで、次のような「Mono.Data.Sqlite」用のドライバを用意する必要があります。
[Mono.Data.Sqlite用ドライバ(MonoDataSqliteDriver.cs)]
using System; using NHibernate.Driver; namespace NHibernateExample.Driver { public class MonoDataSqliteDriver : ReflectionBasedDriver { public MonoDataSqliteDriver() : base( "Mono.Data.Sqlite", "Mono.Data.Sqlite.SqliteConnection", "Mono.Data.Sqlite.SqliteCommand") { } public override bool UseNamedPrefixInSql { get { return true; } } public override bool UseNamedPrefixInParameter { get { return true; } } public override string NamedPrefix { get { return "@"; } } public override bool SupportsMultipleOpenReaders { get { return false; } } } }また、NHibernateではデータプロバイダの呼び出しにReflection(System.Reflection.Assembly.Load)を使用しており、GACにインストールされているアセンブリを呼び出すために、App.config(foo.exe.config)に次の設定が必要になりますが、
<?xml version="1.0" encoding="utf-8" ?> <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <qualifyAssembly partialName="Mono.Data.Sqlite" fullName="Mono.Data.Sqlite, version=2.0.0.0, publicKeyToken=0738eb9f132ed756, culture=neutral" /> </assemblyBinding> </runtime> </configuration>上記設定はMono 2.4上では有効になりませんでした(未対応のようです)。そこで、必要なアセンブリのリンクをMONO_PATHで設定されているディレクトリに作成して、動作確認を行いました。
$ cd ~/lib
$ ln -s /opt/mono/2.4/lib/mono/2.0/Mono.Data.Sqlite.dll .
$ ln -s /opt/mono/2.4/lib/mono/2.0/Mono.Data.Sqlite.dll .
マッピング
次のようなProductsテーブルに関連付けられる、Productクラス、NHibernateマッピングファイルを用意します。ディレクトリ | ファイル |
---|---|
~/src/cs/NHibernateExample | Product.cs |
~/src/cs/NHibernateExample/Test | Product.hbm.xml |
[Productsテーブル]
create table Products( ProductID int not null primary key, ProductName text not null, Price numeric null, ProductDescription text null);
[Productクラス(Product.cs)]
namespace NHibernateExample { public class Product { int _id; string _name; decimal? _price; string _description; public virtual int Id { get { return _id; } set { _id = value; } } public virtual string Name { get { return _name; } set { _name = value; } } public virtual decimal? Price { get { return _price; } set { _price = value; } } public virtual string Description { get { return _description; } set { _description = value; } } public override string ToString() { return "ID:" + _id + " NAME:" + _name + " PRICE:" + _price + " DESCRIPTION:" + _description; } } }
[NHibernateマッピングファイル(Product.hbm.xml)]
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateExample" namespace="NHibernateExample"> <class name="Product" table="Products"> <id name="Id" column="ProductID"> <generator class="assigned" /> </id> <property name="Name" column="ProductName" not-null="true" /> <property name="Price" column="Price" /> <property name="Description" column="ProductDescription" /> </class> </hibernate-mapping>マッピングファイルはNHibernateコンフィグファイル内で指定し、
<mapping file="Product.hbm.xml" />Productクラスはライブラリとしてビルドします。
$ gmcs -t:library -r:NHibernate.dll -out:./Test/NHibernateExample.dll Product.cs -recurse:./Driver/*.cs
Monoで他のDBも使ってみたよ!+(db4o、NHibernate編)5 へ続く。
0 件のコメント:
コメントを投稿