オブジェクト値プロパティの定義と使用
ここでは、シリアル・オブジェクト・プロパティを含む、オブジェクト値プロパティを定義して使用する方法について説明します。
リレーションシップは、異なる永続クラスを関連付ける別の方法になります。"リレーションシップ" を参照してください。
オブジェクト値プロパティの定義
一般に、オブジェクト値プロパティとは、以下のように定義されたプロパティを指します。
Property PropName as Classname;
Classname は、コレクションまたはストリーム以外のオブジェクト・クラスの名前です。(コレクション・プロパティとストリーム・プロパティは特殊なケースです。これについては別途説明しています。)通常、Classname は、登録オブジェクト・クラス、永続クラス、またはシリアル・クラスのいずれかになります (次のセクションを参照)。
このようなプロパティを定義するには、プロパティが参照するクラスを定義してからプロパティを追加します。
バリエーション : CLASSNAME パラメータ
プロパティが永続クラスを基にしていて、そのクラスでサブクラスの代替のプロジェクションを使用している場合 ("永続クラスの定義" を参照) は、追加の手順が必要になります。この場合、そのプロパティの CLASSNAME プロパティ・パラメータに 1 を指定する必要があります。この手順は、このプロパティを InterSystems IRIS® データ・プラットフォームが保存する方法に影響し、そのプロパティがポイントしているオブジェクトを InterSystems IRIS が取得できるようにします。
例えば、MyApp.Payment では NoExtent を指定し、MyApp.CreditCard は MyApp.Payment のサブクラスだとします。MyApp.CurrencyOrder にはタイプ MyApp.CreditCard のプロパティが含まれているとします。このプロパティでは CLASSNAME を 1 に指定する必要があります。
Class MyApp.CurrencyOrder [ NoExtent ]
{
Property Payment as MyApp.CreditCard (CLASSNAME=1);
//other class members
}
SQL 矢印構文は、このシナリオでは機能しません (その代わりに、適切な JOIN を使用できます)。
タイプがシリアル・クラスのプロパティに、CLASSNAME =1 を設定してはいけません。この使用法はサポートされていません。
シリアル・オブジェクトの概要
シリアル・クラスは %SerialObjectOpens in a new tab を拡張します。このようなクラスの目的は、別のオブジェクト・クラスでプロパティとしての役割を果たすことです。シリアル・オブジェクトの値は、親オブジェクト内にシリアル化されます。シリアル・オブジェクトは、埋め込み (または、埋め込み可能) オブジェクトとも呼ばれます。InterSystems IRIS は、シリアル・オブジェクト・プロパティを、それ以外のオブジェクト・プロパティと異なる方法で処理します。以下に、2 つの相違点を示します。
-
シリアル・オブジェクトのプロパティに値を割り当てる前に、シリアル・オブジェクトを作成する %New() を呼び出す必要はありません。
-
シリアル・オブジェクト・プロパティが永続クラスに含まれている場合、シリアル・オブジェクトのプロパティは、永続クラスのエクステント内に保存されます。
シリアル・クラスを定義するには、%SerialObjectOpens in a new tab を拡張するクラスを定義し、プロパティなどのクラス・メンバを必要に応じて追加します。以下に例を示します。
Class Sample.Address Extends %SerialObject
{
/// The street address.
Property Street As %String(MAXLEN = 80);
/// The city name.
Property City As %String(MAXLEN = 80);
/// The 2-letter state abbreviation.
Property State As %String(MAXLEN = 2);
/// The 5-digit U.S. Zone Improvement Plan (ZIP) code.
Property Zip As %String(MAXLEN = 5);
}
オブジェクトの可能な組み合わせ
以下のテーブルに、親クラスとそのクラスのオブジェクト値プロパティの可能な組み合わせを示します。
プロパティが登録オブジェクト・クラス | プロパティが永続クラス | プロパティがシリアル・クラス | |
---|---|---|---|
親クラスが登録オブジェクト・クラス | サポートされる | サポートされるが一般的ではない | サポートされる |
親クラスが永続クラス | サポートされるが一般的ではない | サポートされる | サポートされる |
親クラスがシリアル・クラス | サポートされない | サポートされない | サポートされる |
オブジェクト値プロパティの用語
永続クラスには、オブジェクト値プロパティについての 2 つの用語があります。
-
参照プロパティ (別の永続オブジェクトに基づくプロパティ)
-
埋め込みオブジェクト・プロパティ (シリアル・オブジェクトに基づくプロパティ)
リレーションシップは、異なる永続クラスを関連付ける別の種類のプロパティです。"リレーションシップ" を参照してください。リレーションシップは双方向であり、このトピックで説明するプロパティとは異なります。
オブジェクト・プロパティの値の指定
オブジェクト値プロパティを設定するには、そのプロパティを適切なクラスのインスタンスの OREF と等しくなるように設定します。
ClassA には、ClassB を基にするプロパティ PropB が含まれているというシナリオについて考えてみます。ここでは、ClassB はオブジェクト・クラスです。
Class MyApp.ClassA
{
Property PropB as MyApp.ClassB;
//additional class members
}
さらに、ClassB には、独自のプロパティのセット (Prop1、Prop2、および Prop3) を持つ非シリアル・クラスが含まれています。
MyClassAInstance は、ClassA のインスタンスの OREF だとします。このインスタンスの PropB プロパティの値を設定するには、以下を実行します。
-
ClassB がシリアル・クラスでない場合は、最初に以下を実行します。
-
ClassB のインスタンスの OREF を取得します。
-
このインスタンスのプロパティを必要に応じて設定します。これは後で設定することもできます。
-
その OREF と等しくなるように MyClassAInstance.PropB を設定します。
ClassB がシリアル・クラスの場合は、この手順を省略できます。
-
-
必要に応じて、カスケード・ドット構文を使用して、そのプロパティの各プロパティを設定します (つまり、MyClassAInstance.PropB の各プロパティを設定します)。
例 :
set myclassBInstance=##class(MyApp.ClassB).%New()
set myClassBInstance.Prop1="abc"
set myClassBInstance.Prop2="def"
set myClassAInstance.PropB=myclassBInstance
set myClassAInstance.PropB.Prop3="ghi"
この例では、ClassB インスタンスの作成直後に、このインスタンスのプロパティを直接設定し、その後でカスケード・ドット構文によりさらに間接的に設定しています。
以下の手順では、同等の結果が得られます。
set myClassAInstance.PropB=##class(MyApp.ClassB).%New()
set myClassAInstance.PropB.Prop1="abc"
set myClassAInstance.PropB.Prop2="def"
set myClassAInstance.PropB.Prop3="ghi"
これに対して、ClassB がシリアル・クラスの場合は、ClassB の %New() を呼び出すことなく、以下のように操作できます。
set myClassAInstance.PropB.Prop1="abc"
set myClassAInstance.PropB.Prop2="def"
set myClassAInstance.PropB.Prop3="ghi"
変更の保存
永続クラスを使用している場合は、格納オブジェクト (オブジェクト・プロパティを格納しているインスタンス) を保存します。オブジェクト・プロパティを直接保存する必要はありません。オブジェクト・プロパティは、格納オブジェクトが保存されるときに、自動的に保存されます。
以下の例は、これらの原則を示しています。以下の永続クラスを考えてみます。
Class MyApp.Customers Extends %Persistent
{
Property Name As %String;
Property HomeStreet As %String(MAXLEN = 80);
Property HomeCity As MyApp.Cities;
}
および、
Class MyApp.Cities Extends %Persistent
{
Property City As %String(MAXLEN = 80);
Property State As %String;
Property ZIP As %String;
}
この場合は MyApp.Customers のインスタンスを作成して、そのプロパティを以下のように設定できます。
set customer=##class(MyApp.Customers).%New()
set customer.Name="O'Greavy,N."
set customer.HomeStreet="1234 Main Street"
set customer.HomeCity=##class(MyApp.Cities).%New()
set customer.HomeCity.City="Overton"
set customer.HomeCity.State="Any State"
set customer.HomeCity.ZIP="00000"
set status=customer.%Save()
if $$$ISERR(status) {
do $system.Status.DisplayError(status)
}
これらの手順では、1 つの新しいレコードを MyApp.Customers に追加し、1 つの新しいレコードを MyApp.Cities に追加しています。
MyApp.Cities の %New() を呼び出す代わりに、以下のように既存のレコードを開くことができます。
set customer=##class(MyApp.Customers).%New()
set customer.Name="Burton,J.K."
set customer.HomeStreet="17 Milk Street"
set customer.HomeCity=##class(MyApp.Cities).%OpenId(3)
set status=customer.%Save()
if $$$ISERR(status) {
do $system.Status.DisplayError(status)
}
以下のバリエーションでは、新規顧客 (Customer) の追加プロセスの一環として、既存の市区町村 (City) を開いて、それを変更しています。
set customer=##class(MyApp.Customers).%New()
set customer.Name="Emerson,S."
set customer.HomeStreet="295 School Lane"
set customer.HomeCity=##class(MyApp.Cities).%OpenId(2)
set customer.HomeCity.ZIP="11111"
set status=customer.%Save()
if $$$ISERR(status) {
do $system.Status.DisplayError(status)
}
この変更は、当然、この出身地 (Home City) のどの顧客も参照できるようになります。
オブジェクト値プロパティの SQL プロジェクション
永続クラスは、SQL テーブルとして投影されます。このセクションでは、そのようなクラスの参照プロパティと埋め込みオブジェクト・プロパティが、どのように SQL に投影されるかについて説明します。
参照プロパティ
参照プロパティは、1 つのフィールドとして投影されます。このフィールドは、参照されるオブジェクトの OID の ID 部分を格納します。例えば、顧客オブジェクトには SalesRep オブジェクトを参照する Rep プロパティがあるとします。ある顧客の担当が ID 12 の営業員である場合、その顧客の Rep 列も 12 となります。この値は参照されているオブジェクトの ID 列の特定行の値と一致するので、この値を JOIN あるいはその他の処理を行うために使用できます。
InterSystems SQL では、JOIN を使用する代わりに特別な参照構文を使用して、このような参照を簡単に使用できます。以下に例を示します。
SELECT Company->Name FROM Sample.Employee ORDER BY Company->Name
埋め込みオブジェクト・プロパティ
埋め込みオブジェクト・プロパティは、親クラスのテーブルの複数列として投影されます。プロジェクションの 1 列に、すべての区切り文字と制御文字を含め、シリアル化した形式でオブジェクト全体が格納されます。他の各列は、オブジェクトの各プロパティに対応します。
オブジェクト・プロパティの列名は、そのオブジェクト・プロパティの名前と同じになります。他の列の名前は、オブジェクト・プロパティの名前 + アンダースコア + 埋め込みオブジェクト内のプロパティ名で構成されています。例えば、クラスが Address タイプの埋め込みオブジェクトを含む、Home プロパティを持っているとします。Home には、Street や Country などのプロパティが含まれます。その結果、この埋め込みオブジェクトのプロジェクションには Home_Street および Home_Country という列が存在します。(列名は、タイプ Address からではなく、プロパティ Home から得られます。)
例えば、サンプル・クラス Sample.Person には、タイプ Sample.Address の埋め込みオブジェクトである Home プロパティが含まれます。以下のように、SQL を経由して Home のコンポーネント・フィールドを使用できます。
SELECT Name, Home_City, Home_State FROM Sample.Person
WHERE Home_City %STARTSWITH 'B'
ORDER BY Home_City
埋め込みオブジェクトは、その他にも以下のような複雑な形式のデータを含むことができます。
-
参照プロパティのプロジェクションは、オブジェクト参照を含む読み取り専用フィールドを含みます。詳細は "参照プロパティ" を参照してください。
-
配列のプロジェクションは、テーブルの一部の編集できない単一の列になります。
-
リストのプロジェクションは、投影したフィールドの 1 つであるリスト・フィールドになります。リスト・フィールドの詳細は、"リスト・プロパティの既定のプロジェクション" を参照してください。