永続オブジェクトの概要
ここでは、永続クラスを使用した作業時の理解に役立つ概念について説明します。
ここで示されているサンプルの一部は、Samples-Data サンプル (https://github.com/intersystems/Samples-DataOpens in a new tab) からのものです。(例えば) SAMPLES という名前の専用ネームスペースを作成し、そのネームスペースにサンプルをロードすることをお勧めします。 一般的な手順は、"サンプルのダウンロード" を参照してください。
永続クラス
永続クラスとは、%PersistentOpens in a new tab を継承するあらゆるクラスのことです。永続オブジェクトとは、そのようなクラスのインスタンスのことです。
%PersistentOpens in a new tab クラスは、%RegisteredObjectOpens in a new tab のサブクラスであるため、オブジェクト・クラスになります。オブジェクト・インスタンス・メソッドを提供することに加え、%PersistentOpens in a new tab クラスでは、永続インタフェースも定義します。これは、メソッドのセットです。これらのメソッドにより、データベースにオブジェクトを保存すること、データベースからオブジェクトをロードすること、オブジェクトを削除すること、および存在をテストすることができるようになります。
永続クラスに固有の機能
永続クラスには、他のタイプのクラスでは意味のない数種類のクラス・メンバを含めることができます。
-
ストレージ定義。クラスのデータへのアクセスを制御します。
-
インデックス。クラス内のオブジェクトの一意の識別子を定義できます。"オブジェクト ID" を参照してください。
インデックスにより、特定のフィールドまたはフィールドの組み合わせの一意性を確保する制約を追加することもできます。このようなインデックスの詳細は、"永続クラスの定義" を参照してください。
インデックスのもう 1 つの用途は、クエリの実行速度を速くするために、クラスに関連付けられ頻繁に要求されるデータのソート済み特定サブセットを定義することです。例えば、一般に、特定のフィールドを使用する WHERE 節がクエリに含まれている場合は、そのフィールドにインデックスが作成されていると、クエリの実行速度が速くなります。一方、そのフィールドにインデックスがない場合、エンジンは、すべての行に対して指定の条件と一致しているかどうかを確認するフル・テーブル・スキャンを実行する必要があります。これは、テーブルが巨大になると、負荷の高い操作になります。"永続クラスのその他のオプション" を参照してください。
-
外部キー。データが追加または変更された場合に、使用するテーブル間に、参照整合性制約を確立します。リレーションシップ・プロパティを使用すると、システムはリレーションシップを自動的に外部キーとして扱います。リレーションシップを使用しない場合や、追加する理由が別にある場合は、外部キーを追加することもできます。
外部キーの詳細は、"永続クラスのその他のオプション" を参照してください。
-
トリガ。特定のイベントの発生時 (具体的には、レコードの挿入時、変更時または削除時) に自動的に実行されるコードを定義します。
トリガの詳細は、"永続クラスのその他のオプション" を参照してください。
また、クラス・メソッドやクラス・クエリは、ストアド・プロシージャOpens in a new tabとして呼び出せるように定義できます。このストアド・プロシージャは SQL から呼び出せます。
既定の SQL プロジェクションの概要
どのような永続クラスについても、コンパイラが SQL テーブル定義を生成します。この定義により、オブジェクト・インタフェースに加えて、保存されたデータに SQL でアクセスできます。
このテーブルには、保存されたオブジェクトごとに 1 つのレコードが格納されています。また、このテーブルは InterSystems SQL でクエリできます。以下に、Sample.Person テーブルのクエリ結果を示します。

以下のテーブルに、既定のプロジェクションをまとめます。
投影元 (オブジェクト・コンセプト) | 投影先 (リレーショナル・コンセプト) |
---|---|
パッケージ | スキーマ |
クラス | テーブル |
OID | ID フィールド |
データ型プロパティ | フィールド |
参照プロパティ | 参照フィールド |
埋め込みオブジェクト | 一連のフィールド |
リスト・プロパティ | リスト・フィールド |
配列プロパティ | 子テーブル |
ストリーム・プロパティ | BLOB |
インデックス | インデックス |
クラス・メソッド | ストアド・プロシージャ |
他のトピックでは、詳細情報を示し、変更可能な内容について説明します。
-
テーブル名と、そのテーブルが属するスキーマの名前の詳細は、"永続クラスの定義" を参照してください。
同じトピックでは、サブクラスのプロジェクションを制御する方法についても説明しています。
-
リテラル・プロパティのプロジェクションについての詳細は、"リテラル・プロパティの定義と使用" を参照してください。
-
コレクション・プロパティのプロジェクションについての詳細は、"コレクション・プロパティのストレージと SQL プロジェクション" を参照してください。
-
ストリーム・プロパティのプロジェクションについての詳細は、"ストリームを使用した作業" を参照してください。
-
オブジェクト値プロパティのプロジェクションについての詳細は、"オブジェクト値プロパティの定義と使用" を参照してください。
-
リレーションシップのプロジェクションについての詳細は、"リレーションシップの定義と使用" を参照してください。
オブジェクト ID
初めてオブジェクトを保存するとき、システムでは ID (ここで説明します) と OID (次のセクションで説明します) の 2 つの永続識別子が作成されます。後でこれらの識別子を使用して、保存したオブジェクトにアクセスしたり、これらを削除することができます。
オブジェクト ID はより一般的に使用される識別子であり、すべての永続クラスで利用できる %OpenId()、%ExistsId()、%DeleteId() などのメソッドを呼び出す際には、この ID を最初の引数として使用します。
ID の特定
システムは、ID として使用する整数を自動的に生成できます。しかし、多くの場合、アプリケーションにとってもっと意味のある ID があると便利であるため、一般的には IdKey インデックス定義を永続クラスに追加し、ここでこのインデックスが ID 値を提供するプロパティを参照します。以下の例では、SSN プロパティを参照する IdKey インデックスを追加します。
Class MyApp.Person Extends %Persistent
{
Index MainIDX On SSN [ Idkey ];
Property SSN As %String;
// other properties
}
この例では、人物の SSN は ID として機能します (また、%OpenId()、%ExistsId()、%DeleteId() などのメソッドで使用できます)。以下に例を示します。
set person=##class(MyApp.Person).%OpenId("123-45-6789")
クラスに IdKey インデックスを追加すると、コンパイラはそのクラスに追加のメソッド (インデックス・メソッドと呼ばれる) を生成します。これらを使用して、オブジェクトにアクセスしたり、オブジェクトを削除することができます。インデックス・メソッドには indexNameOpen()、indexNameExists()、indexNameDelete() が含まれます。indexName は IdKey インデックスの名前です。IdKey インデックスが 1 つのプロパティのみを参照する場合、これらのメソッドはそのプロパティの値を最初の引数として受け入れます。以下に例を示します。
set person=##class(MyApp.Person).MainIDXOpen("123-45-6789")
以下のように、複数のプロパティを参照する IdKey インデックスを持つことができます。
Class MyApp.Account Extends %Persistent
{
Index MainIDX On (CountryCode,RegionalID) [ Idkey ];
Property CountryCode As %String;
Property RegionalID As %String;
// other properties
}
このようなクラスでは、ID はより複雑な形式になります。ID は、パイプ || 文字のペアで連結された、IdKey インデックスで使用されるプロパティ値で構成されます。この場合、生成されたインデックス・メソッドを使用する方が簡単です。期待される引数は、IdKey インデックスで使用されるプロパティ値 (このインデックスで使用される順序で) です。以下に例を示します。
set account=##class(MyApp.Account).MainIDXOpen("US","1234567")
オブジェクト ID から SQL へのプロジェクション
オブジェクトの ID は、対応する SQL テーブルで使用できます。可能な場合、InterSystems IRIS は ID というフィールド名を使用します。また、InterSystems IRIS には、どのフィールド名を使用しているかわからない場合でも、ID にアクセスする方法があります。このシステムは、以下のとおりです。
-
オブジェクト ID は、オブジェクトのプロパティではないため、プロパティとは異なる扱いを受けます。
-
ID という名前のプロパティ (どのような大文字小文字の組合せであっても) がクラスに含まれていない場合、テーブルにはフィールド ID も含まれるようになり、そのフィールドにオブジェクト ID が格納されます。この例については、前のセクションを参照してください。
-
ID という名前 (どのような大文字小文字の組合せであっても) を SQL に投影したプロパティがクラスに含まれている場合、テーブルにはフィールド ID1 も含まれるようになり、このフィールドにオブジェクト ID の値が保持されます。
同様に、ID および ID1 として投影されたプロパティがクラスに含まれている場合、テーブルにはフィールド ID2 も含まれるようになり、このフィールドにオブジェクト ID の値が保持されます。
-
すべての場合で、テーブルに疑似フィールド %ID も用意され、オブジェクト ID の値も保持されます。
SQL でのオブジェクト ID
InterSystems IRIS は、ID フィールドに一意性を強制します (実際の名前は、どのようなものであってもかまいません)。また、InterSystems IRIS は、このフィールドの変更を禁止します。つまり、このフィールドに対する SQL UPDATE または INSERT 操作は実行できないということです。例として、新しいレコードをテーブルに追加するために必要な SQL を以下に示します。
INSERT INTO PERSON (FNAME, LNAME) VALUES (:fname, :lname)
この SQL は ID フィールドを参照しません。InterSystems IRIS は、ID フィールドの値を生成し、要求されたレコードの作成時にその値を挿入します。
オブジェクト OID
ID のほかに、保存した各オブジェクトには追加のパラメータ識別子、OID があります。OID にはクラス名も含まれていて、データベース内で一意です。
%PersistentOpens in a new tab クラスは、OID を使用する追加のメソッドを提供します。これには、%Open()、%Exists()、%Delete() が含まれます。引数として OID を使用するメソッドは、そのメソッドの名前に Id が含まれていません。このようなメソッドは、ほとんど使用されません。
永続オブジェクトがそのデータベースに保存されると、その参照属性 (つまり、他の永続オブジェクトへの参照) の値はすべて OID 値として保存されます。OID を持たないオブジェクト属性については、オブジェクトのリテラル値が、その他のオブジェクト状態と共に保存されます。
OID は SQL を介して利用することはできません。