
現在の実際のプロジェクトでオブジェクト指向データベース管理システム(OSBMS)を使用するかどうか。 それらを使用する場合と、使用しない場合
OSBMS を使用する利点は次のとおりです。
- アプリケーションとデータベースのデータモデルの不一致の問題はありません( インピーダンスの不一致 )。 すべてのデータは、アプリケーションモデルと同じ形式でデータベースに保存されます。
- DBMS側でデータモデルを個別にサポートする必要はありません。
- データソースレベルのすべてのオブジェクトは厳密に型指定されています。 これ以上文字列の列名はありません! オブジェクト指向データベースとそれと連携するコードのリファクタリングは、単調で退屈なプロセスではなく自動化されました。
この記事では、DBMS DBMSの使用を開始するために必要なすべての事項について説明しています。
Db4oのインストール
今日、 db4oは最も人気のあるオブジェクト指向データベース管理システムの1つです。
開始するには、 db4o Webサイトから最新の配布キットをダウンロードします(Java、.NET 2.0、3.5のバージョンがあります)。 執筆時点では、最新バージョンは7.9です。 このディストリビューションには、IDE(Eclipse、Visual Studio)の便利なプラグインであるObject Manager Enterprise(OME)も含まれています。これにより、データベースを自律的に操作できます。 OMEは最後の生産的な配布 (現在7.4)に含まれていないため、OSBMSに慣れるためにバージョン7.9をお勧めします。
記事の後半では、例としてC#を使用します。 Javaの場合、.NET 3.5の使用が前提条件であるLINQセクションを除き、例は似ています。
適切な場所にdb4oをインストールすると、キットに含まれる優れたチュートリアルを見つけることができます。 トピック自体があなたにとって興味深いと思われる場合、この記事を読んだ後に回すことをお勧めするのは彼にとってです。
db4oおよびDBMS自体を操作するためのすべてのソフトウェアは、非営利的な使用には無料です。
データベースへの接続
db4oで実験を行うには、IDEで任意のタイプのプロジェクト(コンソールアプリケーションなど)を作成し、db4oアセンブリ(パッケージ)へのリンクを追加します: Db4objects.Db4o.dllおよびDb4objects.Db4o.Linq.dll (必要な場合)。
アプリケーションのオブジェクトベースでアクションを実行するには、最初に行う必要があるのは、タイプIObjectContainerのオブジェクトを取得することです。 これがデータベースのファサードです。それを通じて、データベースへのクエリが実行され、データの選択、保存、追加、削除が行われます。
オブジェクトを取得する方法は、データベースへの接続のタイプによって異なります。
最も簡単な方法-データベースはローカルファイルにあり、アプリケーションが直接アクセスします。 これは次のように行われます。
//
IObjectContainer db = Db4oFactory.OpenFile(filename);
try
{
//
}
finally
{
// ,
db.Close();
}
* This source code was highlighted with Source Code Highlighter .
この場合のデータベースファイルは排他モードで開かれるため、マルチユーザーアプリケーションを実装するときに問題が発生します。 ただし、このソリューションは、複雑なデータモデルを持ち、アプリケーションの起動時にこのデータを保存する必要があるシングルユーザーのスタンドアロンアプリケーションに最適です。 CADアプリケーションの例。
次の方法。 マルチユーザーモード、つまり、同じデータベースに対して複数のIObjectContainerが同時に存在する可能性をサポートするには、クライアントサーバーアーキテクチャを使用する必要があります。 クライアントとサーバーが同じアプリケーション内で動作する場合、これは次のように行われます。
//
IObjectServer server = Db4oFactory.OpenServer(filename, 0);
try
{
//
IObjectContainer client = server.OpenClient();
IObjectContainer client2 = server.OpenClient();
// IObjectContainer
client.Close();
client2.Close();
}
finally
{
// ,
server.Close();
}
* This source code was highlighted with Source Code Highlighter .
この場合、サーバーを作成するときに、データベースファイルを指定する必要があります。 これは、データベースへのすべてのタイプの接続に対して実行する必要があります-ファイルへのバインドは常に残ります(1つのファイル-1つのデータベース)。 ところで、そのようなファイルは、以前に作成されていなかった場合、要求に応じて自動的に作成されます。
OpenServer関数の2番目のパラメーター-0に等しいポート番号は、 server.OpenClient()を使用して作成されたローカルクライアントのみがサーバーを使用できることを意味します。
与えられた例は人為的です。 実際のアプリケーションでは、クライアントは別のスレッドで開く可能性が最も高くなります。
そして最後のオプションは、リモートクライアントの場合に前のオプションを拡張することです。
//
IObjectServer server = Db4oFactory.OpenServer(filename, serverPort);
server.GrantAccess(serverUser, serverPassword);
try
{
IObjectContainer client = Db4oFactory.OpenClient( "localhost" , serverPort,
serverUser, serverPassword);
//
client.Close();
}
finally
{
server.Close();
}
* This source code was highlighted with Source Code Highlighter .
このオプションは、次の点で前のオプションと異なります。
- OpenServerを呼び出すときにサーバーがリッスンするポートの実際の値を指定します(TCP / IPを使用)。
- データベースへのアクセスの許可データが示されます。
- クライアントはDb4oFactory.OpenClientを使用して作成されるため、これは別のスレッドだけでなく、リモートマシンで実行されている完全に異なるアプリケーションでも発生する可能性があります。
データを操作する
アプリケーションのどこかで、 UserクラスがLogin 、 Password、およびAgeフィールドで宣言され、 dbがIObjectContainer型のオブジェクト(最後のセクションで取得したオブジェクト)であるとします。
オブジェクトの保存(INSERT)
User user1 = new User("Vasya", "123456", 25);
db.Store(user1);
* This source code was highlighted with Source Code Highlighter .
以上です! データベースに保存できるオブジェクト、これらのオブジェクトの構造、その他を事前または手動で設定する必要はありません。 最初のオブジェクトを保存すると、OSBMSがすべての作業を行います。
データクエリ(SELECT)
データベースに保存されているデータを照会するには、いくつかの方法があります。
自然クエリ(Native Queries、NQ)の使用は、ODBのデータに対してクエリを実行するための柔軟で強力かつ便利な方法です。
IList<User> result = db.Query<User>(usr => usr.Age >= 18
&& usr.Login.StartsWith("V"));
* This source code was highlighted with Source Code Highlighter .
ここでは、 Userクラスのオブジェクトに対してリクエストが行われ、この例では可能なすべてが厳密に入力されています。 オブジェクトは、条件を満たすようにフィルターされます。ユーザーの年齢が18歳以上であり、ユーザー名が大文字の「V」で始まっています。 ラムダ式の代わりに、 Predicate <T>型のデリゲートまたはオブジェクトをQuery関数に渡すことができます。 述部<T>は、タイプTのパラメーターを取り、 boolを返す単一のMatch関数を含むインターフェースです。 Queryは、 Matchがtrueを返すオブジェクトを返します 。
OOBDの概念は、統合言語クエリ(LINQ)を使用するという考えに完全に基づいています。
LINQを使用して以前のクエリを書き換えます。
IEnumerable <User> result = from User usr in db
where usr.Age >= 18 && usr.Login.StartsWith( "V" )
select usr;
* This source code was highlighted with Source Code Highlighter .
リクエストは再び強く型付けされ、リファクタリングが容易です。
NQおよびLINQ以外のクエリ実行メソッドがあります。
- サンプルごとのクエリ(例ごとのクエリ)。 最も簡単ですが、強力ではありません。 データサンプリングは、オブジェクトの事前に準備されたインスタンス(サンプル)との比較に基づいて実行されます。 サンプル結果は強く型付けされていません。 この方法が役立つ状況を想像することは困難です。
- ソーダ。 db4oが動作する低レベルのクエリ言語。 SODA構文を使用するリクエストは、タイプセーフではなく、強く型付けされておらず、多くのスペースを占有しますが、可能な限り柔軟で、必要に応じてアプリケーションのパフォーマンスを向上させることができます。
オブジェクトの更新(UPDATE)
オブジェクトを更新する前に、データベースからオブジェクトを抽出し、それを変更して保存します。
User usr = db.Query<User>(usr => usr.Login == "Vasya" )[0];
usr.SetPassword( "111111" );
db.Store(usr);
* This source code was highlighted with Source Code Highlighter .
オブジェクトの削除(DELETE)
オブジェクトの削除も同様です。
User usr = db.Query<User>(usr => usr.Login == "Vasya" )[0];
db.Delete(usr);
* This source code was highlighted with Source Code Highlighter .
複合オブジェクト
この瞬間まで、基本型( stringおよびint )のフィールドのみを含む非常に単純なUserオブジェクトの操作方法を検討しました。 ただし、オブジェクトは複合であり、他のオブジェクトを参照できます。 たとえば、 Userクラスでは、 friendsフィールドを宣言できます。
public class User
{
// ...
IList<User> friends = new List <User>();
}
* This source code was highlighted with Source Code Highlighter .
このクラスでのすべての操作は以前と同様に実行されます-複合フィールドはデータベースに正しく保存されますが、いくつかの機能があります。
前のセクションで行ったように、特定のユーザー( User )のオブジェクトをデータベースからロードしようとしているとします。 ユーザー自身がロードされている場合、彼の友人、次に彼の友人の友人などがロードされる必要があります。 これにより、すべてのユーザーオブジェクトをメモリにロードしなければならない場合があります。ユーザーが他のタイプのオブジェクト、データベース全体への参照を持っている場合でも。 当然、そのような効果は望ましくありません。 したがって、デフォルトでは、選択オブジェクト自体とそれらが参照するオブジェクトのみが、5番目のネストレベルまでロードされます。 いくつかの状況ではこれは非常に多く、他の状況では十分ではありません。 アクティベーションの深さと呼ばれる、このパラメーターを構成する方法があります。
//
db.Ext().Configure().ActivationDepth(2);
// User
db.Ext().Configure().ObjectClass( typeof (User)).MinimumActivationDepth(3);
db.Ext().Configure().ObjectClass( typeof (User)).MaximumActivationDepth(4);
// User ( )
db.Ext().Configure().ObjectClass( typeof (User)).CascadeOnActivate( true );
* This source code was highlighted with Source Code Highlighter .
一度にすべてと特定のクラスの両方のアクティベーションの深さを確立する例を次に示します。 Ext()関数は、拡張IExtObjectContainerを返し、データベース構成設定などの高度な機能にアクセスします。 これは、メインのIObjectContainerインターフェイスを詰まらせないように、便宜上行われています。
リクエストがすでに完了しているが、一部のデータが欠落している、つまり必要なデータがすべてアクティブ化されていない(メモリにロードされていない)場合、別の保存オブジェクトに適用されるActivateメソッドを使用できます:
// – , –
db.Activate(usr, 5);
* This source code was highlighted with Source Code Highlighter .
複合オブジェクトを保存するときに、同様の問題が発生します。 デフォルトでは、オブジェクト自体のフィールドのみが保存され、参照先のオブジェクトは保存されません。 つまり、 更新の深さはデフォルトで1に等しく、次のように変更できます。
//
db.Ext().Configure().UpdateDepth(2);
// User
db.Ext().Configure().ObjectClass( typeof (User)).UpdateDepth(3);
// User ( )
db.Ext().Configure().ObjectClass( typeof (User)).CascadeOnUpdate( true );
* This source code was highlighted with Source Code Highlighter .
オブジェクトを削除する場合、カスケード削除もデフォルトでは発生しません。削除されたオブジェクトによって参照されるオブジェクトは残ります。 オブジェクトを削除する場合のDBMSの動作は、次のように構成できます。
// ( )
db.Ext().Configure().ObjectClass( typeof (User)).CascadeOnDelete( true );
* This source code was highlighted with Source Code Highlighter .
「除去の深さ」の概念は提供されていません。
取引
コンテナ( IObjectContainer )が開かれるたびに、トランザクションコンテキストが暗黙的に作成されます。 Close操作が実行されると、現在のトランザクションが自動的にコミットされます。
より柔軟なトランザクション管理のために、 IObjectContainerインターフェイスには2つのメソッドがあります。
- コミット() 。 データベース内のすべての変更の記録を使用したトランザクションの明示的な完了(コミット)。
- ロールバック() 。 トランザクションのロールバック-トランザクション(コンテナ)が開かれてから発生した変更は、データベースに記録されません。
おわりに
この記事の目的は、リレーショナルDBMSを使用した既存の開発アプローチに非常に強力な代替手段があることを示すことです。 オブジェクトデータベース自体を使用するアプローチは非常に近代的です。JavaやC#などのプログラミング言語の開発で見られる主な傾向に遅れをとらないDBMSです。
この記事には、OSBMSとの連携を開始し、実際のアプリケーションを作成するのに十分な資料があります。 ただし、ここでは、Webアプリケーションのパフォーマンスや開発に関連する問題など、多くの問題に対処しませんでした。
いずれにせよ、今日実際にオブジェクト指向DBMSを使用し始めていない場合、少なくともこれがプロジェクトにとって最適なソリューションであるかどうかを検討する必要がありますか?