オブジェクトの永続性とJava

オブジェクトの耐久性、つまり永続性は、データベースへのオブジェクトの保存の問題に関連してよく使用される用語です。永続性はトランザクションの整合性で動作することが期待されているため、厳しい条件が適用されます。(トランザクション処理の詳細については、この記事の「リソース」セクションを参照してください。)対照的に、標準の言語ライブラリおよびパッケージを通じて提供される言語サービスには、トランザクションの制約がないことがよくあります。

この記事で説明するように、証拠によると、単純なJavaの永続性は言語自体に由来する可能性が高く、高度なデータベース機能はデータベースベンダーによって提供されます。

オブジェクトは島ではありません

現実の世界では、他のオブジェクトとの関係がないオブジェクトを見つけることはめったにありません。オブジェクトは、オブジェクトモデルのコンポーネントです。オブジェクトの耐久性の問題は、オブジェクトが相互に関係しているために相互接続されていることを観察すると、オブジェクトモデルの耐久性と分布の問題を超えます。

データストレージへのリレーショナルアプローチは、タイプごとにデータを集約する傾向があります。テーブルの行は、ディスク上の同じタイプのオブジェクトの物理的な集合体を表します。オブジェクト間の関係は、多くのテーブルで共有されるキーによって表されます。リレーショナルデータベースでは、データベースの編成を通じて、一緒に使用される可能性のあるテーブルをデータベースセグメントなどの同じ論理パーティションに同じ場所に配置(またはクラスター化)できる場合がありますが、オブジェクトの関係をデータベースに格納するメカニズムはありません。したがって、オブジェクトモデルを構築するために、これらの関係は、テーブル結合と呼ばれるプロセスで実行時に既存のキーから構築されます。これは、と呼ばれるリレーショナルデータベースのよく知られたプロパティと同じです。データの独立性。オブジェクトデータベースのほぼすべてのバリアントは、従来のリレーショナルデータベースよりも複雑なオブジェクト関係を含むシステムのパフォーマンスを向上させるメカニズムを提供します。

クエリまたはナビゲートするには?

オブジェクトをディスクに保存する際、ナビゲーションアクセスに対応するために関連オブジェクトを同じ場所に配置するか、オブジェクトをタイプ別に集約して述語ベースのアクセス(クエリ)を容易にするテーブルのようなコレクションにオブジェクトを保存するか、またはその両方を選択する必要があります。 。永続ストレージ内のオブジェクトのコロケーションは、リレーショナルデータベースとオブジェクト指向データベースが大きく異なる領域です。クエリ言語の選択は、考慮すべきもう1つの領域です。構造化照会言語(SQL)とその拡張機能により、リレーショナルシステムに述語ベースのアクセスメカニズムが提供されています。オブジェクトクエリ言語(OQL)は、ODMGによって標準化されたSQLのオブジェクトバリアントですが、この言語のサポートは現在不十分です。ポリモーフィックメソッドは、オブジェクトのコレクションのセマンティッククエリを構築する際に前例のないエレガンスを提供します。例えば、のポリモーフィックな動作を想像してくださいacccountと呼ばれisInGoodStandingます。良好な状態のすべてのアカウントに対してブール値trueを返し、それ以外の場合はfalseを返す場合があります。ここでinGoodStanding、ビジネスルールに基づいて異なる方法で実装されているアカウントのコレクションを、良好な状態のすべてのアカウントに対してクエリするエレガンスを想像してみてください。次のようになります。

setOfGoodCustomers = setOfAccounts.query(account.inGoodStanding());

既存のオブジェクトデータベースのいくつかは、C ++およびSmalltalkでこのようなクエリスタイルを処理できますが、より大きな(たとえば、500ギガバイト以上の)コレクションやより複雑なクエリ式では処理が困難です。OracleやInformixなどのリレーショナルデータベース企業のいくつかは、同じ結果を達成するために、他のSQLベースの構文をまもなく提供する予定です。

永続性とタイプ

オブジェクト指向言語愛好家は、永続性と型はオブジェクトの直交するプロパティであると言うでしょう。つまり、一方のプロパティが他方に影響を与えてはならないため、同じタイプの永続オブジェクトと一時オブジェクトは同一である可能性があります。別の見方では、永続性は永続化可能なオブジェクトによってのみサポートされる動作であり、特定の動作は永続的なオブジェクトにのみ適用される場合があります。後者のアプローチでは、永続ストレージに自分自身を格納および取得するように永続オブジェクトに指示するメソッドが必要ですが、前者は、多くの場合仮想メモリシステムを拡張することにより、アプリケーションにオブジェクトモデル全体のシームレスなビューを提供します。

正規化と言語の独立性

言語内の同じタイプのオブジェクトは、インターフェイスが表示される順序に関係なく、同じレイアウトで永続ストレージに格納する必要があります。オブジェクトレイアウトをこの一般的な形式に変換するプロセスは、まとめてオブジェクト表現の正規化と呼ばれます。同じ言語で記述されているが、異なるシステムでコンパイルされた静的型付け(Javaではない)オブジェクトを使用するコンパイル言語では、永続ストレージで同じように表現する必要があります。

正規化の拡張は、言語に依存しないオブジェクト表現に対応します。オブジェクトを言語に依存しない方法で表現できる場合、同じオブジェクトの異なる表現が同じ永続ストレージを共有する可能性があります。

このタスクを実行するための1つのメカニズムは、インターフェイス定義言語(IDL)を介して追加レベルの間接参照を導入することです。オブジェクトデータベースインターフェイスは、IDLおよび対応するデータ構造を介して作成できます。IDLスタイルのバインディングの欠点は2つあります。1つは、追加レベルの間接参照には常に追加レベルの変換が必要であり、システムの全体的なパフォーマンスに影響を与えます。次に、特定のベンダーに固有であり、アプリケーション開発者にとって価値のあるデータベースサービスの使用を制限します。

同様のメカニズムは、SQLの拡張を通じてオブジェクトサービスをサポートすることです。リレーショナルデータベースベンダーと小規模なオブジェクト/リレーショナルベンダーは、このアプローチの支持者です。ただし、これらの企業がオブジェクトストレージのフレームワークの形成にどの程度成功するかはまだわかりません。

しかし、疑問は残ります。オブジェクトの永続性はオブジェクトの動作の一部なのか、それとも個別のインターフェイスを介してオブジェクトに提供される外部サービスなのか。オブジェクトのコレクションとそれらをクエリするためのメソッドはどうですか?リレーショナル、拡張リレーショナル、およびオブジェクト/リレーショナルアプローチは、言語間の分離を提唱する傾向がありますが、オブジェクトデータベース(およびJava言語自体)は、永続性を言語に固有のものと見なします。

シリアル化によるネイティブJavaの永続性

オブジェクトのシリアル化は、Javaオブジェクトとプリミティブをストリームに格納および取得するためのJava言語固有のメカニズムです。C ++オブジェクトをシリアル化するための商用のサードパーティライブラリが以前から存在していましたが、C ++がオブジェクトのシリアル化のためのネイティブメカニズムを提供したことは一度もないことに注意してください。Javaのシリアル化の使用方法は次のとおりです。

//「foo」をストリーム(ファイルなど)に書き込む

//ステップ1.出力ストリームを作成します

//つまり、バイトを受信するバケットを作成します

FileOutputStream out = new FileOutputStream( "fooFile");

//ステップ2.ObjectOutputStreamを作成します

//つまり、ホースを作成し、その頭をバケツに入れます

ObjectOutputStream os = new ObjectOutputStream(out)

//ステップ3.文字列とオブジェクトをストリームに書き込みます

//つまり、ストリームをバケットに流します

os.writeObject( "foo");

os.writeObject(new Foo());

//ステップ4.データを宛先にフラッシュします

os.flush();

このWriteobjectメソッドは、fooとその推移閉包、つまり、グラフ内のfooから参照できるすべてのオブジェクトをシリアル化します。ストリーム内には、シリアル化されたオブジェクトのコピーが1つだけ存在します。オブジェクトへの他の参照は、スペースを節約し、循環参照を回避するためにオブジェクトハンドルとして保存されます。シリアル化されたオブジェクトは、クラスで始まり、継承階層内の各クラスのフィールドが続きます。

//ストリームからオブジェクトを読み取る

//ステップ1.入力ストリームを作成します

FileInputStream in = new FileInputStream( "fooFile");

//ステップ2.オブジェクト入力ストリームを作成します

ObjectInputStream ins = new ObjectInputStream(in);

//ステップ3.あなたが読んでいるものを知った

文字列fooString =(String)ins.readObject();

Foo foo =(Foo)s.readObject();

オブジェクトのシリアル化とセキュリティ

デフォルトでは、シリアル化はストリームから非静的および非一時フィールドを読み書きします。この特性は、プライベートトランジェントとしてシリアル化できないフィールドを宣言することにより、セキュリティメカニズムとして使用できます。クラスがまったくシリアル化されていない可能性がある場合は、をスローするメソッドを実装する必要がwriteObjectありreadObjectますNoAccessException

トランザクションの整合性を備えた永続性:JDBCの紹介

X / OpenのSQLCLI(クライアントレベルインターフェイス)とMicrosoftのODBC抽象化をモデルにしたJavaデータベースコネクティビティ(JDBC)は、基盤となるデータベース管理システム(DBMS)に依存しないデータベースコネクティビティメカニズムを提供することを目的としています。少なくともANSISQL-2エントリレベルAPIをサポートする必要があります。これにより、サードパーティのツールベンダーとアプリケーションにデータベースアクセスに十分な柔軟性が与えられます。

JDBCは、Javaシステムの他の部分と一貫性があるように設計されています。ベンダーは、ODBCよりも強く型付けされたAPIを作成することをお勧めします。これにより、コンパイル時の静的型チェックが向上します。

最も重要なJDBCインターフェースの説明は次のとおりです。

  • java.sql.Driver.Manager ドライバのロードを処理し、新しいデータベース接続のサポートを提供します。

  • java.sql.Connection 特定のデータベースへの接続を表します。

  • java.sql.Statement 特定の接続でSQLステートメントを実行するためのコンテナーとして機能します。

  • java.sql.ResultSet 結果セットへのアクセスを制御します。

JDBCドライバーはいくつかの方法で実装できます。最も簡単なのは、ODBCへのブリッジとしてドライバーを構築することです。このアプローチは、高性能を必要としないツールやアプリケーションに最適です。より拡張可能な設計では、公開されたプロトコルを介してDBMSサーバーにアクセスするJDBCネットワークドライバーを提供することにより、DBMSサーバーに追加レベルの間接参照を導入します。ただし、最も効率的なドライバーは、DBMS独自のAPIに直接アクセスします。

オブジェクトデータベースとJavaの永続性

業界で進行中の多くのプロジェクトは、オブジェクトレベルでJavaPersistenceを提供しています。ただし、この記事の執筆時点では、Object DesignのPSE(Persistent Storage Engine)とPSE Proだけが、完全にJavaベースのオブジェクト指向データベースパッケージです(少なくとも私が知っていることです)。PSEおよびPSEProの詳細については、「リソース」セクションを確認してください。

Java開発は、特に開発プロセスのタイムラインにおいて、ソフトウェアベンダーの従来の開発パラダイムからの逸脱をもたらしました。たとえば、PSEとPSE Proは、異種環境で開発されています。また、開発プロセスにはリンクステップがないため、開発者は互いに独立したさまざまな機能コンポーネントを作成でき、その結果、より優れた、より信頼性の高いオブジェクト指向コードが実現します。

PSE Proには、システム障害によって中止されたトランザクションから破損したデータベースを回復する機能があります。この追加機能を担当するクラスは、PSEリリースには存在しません。 2つの製品の間に他の違いはありません。これらの製品は、私たちが「ドリブルウェア」と呼んでいるものです。これは、新しいコンポーネントを接続することで機能を強化するソフトウェアリリースです。それほど遠くない将来、大規模なモノリシックソフトウェアを購入するという概念は過去のものになるでしょう。サイバースペースの新しいビジネス環境とJavaコンピューティングにより、ユーザーは必要なオブジェクトモデル(オブジェクトグラフ)の部分のみを購入できるようになり、最終製品がよりコンパクトになります。

PSEは、開発者が作成したクラスファイルを後処理して注釈を付けることで機能します。PSEの観点からは、オブジェクトグラフのクラスは、永続対応または永続対応のいずれかです。永続対応クラスは永続化できますが、永続認識クラスは永続オブジェクトを操作できます。永続性は特定のクラスにとって望ましい動作ではない可能性があるため、この区別が必要です。クラスファイルポストプロセッサは、クラスに次の変更を加えます。