コールバック・メソッドの定義
コールバック・メソッドは、システム・メソッドによって呼び出され、ユーザが提供する追加処理を行うことができます。コールバック・メソッドは、%On または On で始まり、通常、それらを呼び出すメソッドの名前が続く名前を持つことによって識別できます。
コールバック・メソッドを実装しているシステム・メソッドを実行すると、そのメソッドによりコールバック・メソッドが呼び出されます。例えば、%OnDelete() が実装されている場合、%Delete() が %OnDelete() を呼び出します。
コールバック・メソッドは、直接実行しないでください。
プライベート・メソッドのコールバックのドキュメントは、[クラスリファレンス] の右上隅の [プライベート] チェック・ボックスにチェックが付いている場合にのみ、クラスリファレンスに表示されます。
コールバックおよびトリガ
SQL とオブジェクト・アクセスの両方を使用するアプリケーションでトリガを実装する場合、通常はオブジェクト・アクセスの同じ場所で同じロジックを呼び出すことをお勧めします。例えば、行を削除するときに監査レコードを挿入する場合は、オブジェクトを削除するときにも監査レコードを挿入します。
Foreach = row/object を使用してトリガが定義されている場合、トリガはオブジェクト・アクセスの特定の時点でも呼び出されます。"トリガとトランザクション" を参照してください。
ただし、そのようなトリガが作成できない場合に、SQL とオブジェクトの動作を前述のように同期させるには、1 つ以上のコールバックを実装する必要があります。これらの実装では、トリガ定義で使用したロジックと同等のロジックを使用します。以下のコールバック・メソッドには、SQL トリガの該当機能と同等の機能があります。
-
%OnBeforeSave() — BEFORE INSERT、BEFORE UPDATE
-
%OnAfterSave() — AFTER INSERT、AFTER UPDATE
-
%OnDelete() — BEFORE DELETE
トリガの詳細は、"トリガの使用法"、または "InterSystems SQL リファレンス" の "CREATE TRIGGER" ページを参照してください。
%OnAddToSaveSet()
このインスタンス・メソッドは、%AddToSaveSet() によって現在のオブジェクトが SaveSet に追加されるときに必ず呼び出されます。%AddToSaveSet() は、以下によって呼び出すことができます。
-
%PersistentOpens in a new tab のインスタンスに対する %Save()
-
%SerialObjectOpens in a new tab のインスタンスに対する %GetSwizzleObject()
-
参照オブジェクトの %AddToSaveSet()
%OnAddToSaveSet() が他のオブジェクトを修正する場合、%OnAddToSaveSet() は修正されたオブジェクトで %AddToSaveSet() を呼び出す必要があります。%AddToSaveSet() を %OnAddToSaveSet() から呼び出す際、depth を最初の引数として渡し、1 (リテラルの 1) を 2 番目の引数として渡します。
例えば、MyPerson オブジェクトで %Save() を呼び出すとき、システムは MyPerson が参照するオブジェクトのリストを生成します。SaveSet は保存されたオブジェクトと、それを参照するすべてのオブジェクトで構成される、オブジェクトのリストです。この例では、SaveSet は参照されたオブジェクト MySpouse や MyDoctor などを含みます。詳細は、"オブジェクトの保存" を参照してください。
%OnAddToSaveSet() のシグニチャは以下のとおりです。
Method %OnAddToSaveSet(depth As %Integer,
insert As %Integer,
callcount As %Integer)
As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
以下はその説明です。
SaveSet 構文の内部状況を表す %AddToSaveSet() から渡される整数値。%OnAddToSaveSet() を使用して SaveSet に他の任意のオブジェクトを追加する場合、この値を変更せずに %AddToSaveSet() に渡します。
保存されているオブジェクトが、エクステントに現在挿入されている場合は (1) を、既にエクステントの一部ある場合は (0) を示すフラグ。
このオブジェクトに対して %OnAddToSaveSet が呼び出された回数。オブジェクト・リファレンスはネットワーク化されているという特徴があるため、%AddToSaveSet は同じオブジェクトで複数回呼び出されることがあります。
メソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、保存は失敗してトランザクションはロールバックされます。
%AddToSaveSet() を呼び出すことで、オブジェクトの更新や、新規オブジェクトの生成、オブジェクトの削除、およびオブジェクト自身を現在の SaveSet に含めるかをそのオブジェクトに尋ねることができます。現在のインスタンスや、その下位のいずれかを変更する場合は、変更を行ったことをシステムに伝える必要があります。これを行うには、変更を行ったインスタンスの %AddToSaveSet() を呼び出して、Refresh 引数を 1 に指定します。
%OnAfterSave()、%OnBeforeSave()、および %OnValidateObject() で定義された変更制約は、どれも %OnAddToSaveSet() には適用されません。
%OnAddToSaveSet() を使用してオブジェクトを削除する場合、ダングリング参照をすべて削除するために、%RemoveFromSaveSet() を呼び出す必要があります。
このメソッドは、%Library.RegisteredObjectOpens in a new tab の任意のサブクラスでオーバーライドできます。
%OnAfterBuildIndices()
このクラス・メソッドは、%BuildIndices() メソッドがインデックスを構築し、$SortEnd を実行した後、そして拡張ロックをリリースする直前に (要求されている場合)、%BuildIndices() メソッドによって呼び出されます。
そのシグニチャは、以下のとおりです。
ClassMethod %OnAfterBuildIndices(indexlist As %String(MAXLEN="") = "") As %Status [ Abstract, Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
インデックス名の $List。
%OnAfterDelete()
このクラス・メソッドは、指定したオブジェクトが削除された直後 (%DeleteData() メソッドの呼び出しに成功した直後) に %Delete() または %DeleteId() メソッドによって呼び出されます。このメソッドを使用すると、保存するオブジェクトのスコープ外のアクション (後で発生する通知アクションのキューなど) を実行できます。
そのシグニチャは、以下のとおりです。
ClassMethod %OnAfterDelete(oid As %ObjectIdentity) As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
削除するオブジェクト。
このメソッドは %StatusOpens in a new tab コードを返します。この場合は、失敗のステータスによって %Delete() または %DeleteId() が失敗し、アクティブなトランザクションがある場合は、そのトランザクションのロールバックが発生します。%Delete() または %DeleteId() からエラー (このメソッド自身のエラー、または %DeleteData() で発生したエラー) が返ると、%OnAfterDelete() は呼び出されません。
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnAfterPurgeIndices()
このクラス・メソッドは、%PurgeIndices() メソッドが処理をすべて完了した後、%PurgeIndices() メソッドによって呼び出されます。
そのシグニチャは、以下のとおりです。
ClassMethod %OnAfterPurgeIndices(indexlist As %String(MAXLEN="") = "") As %Status [ Abstract, Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
インデックス名の $List。
%OnAfterSave()
このインスタンス・メソッドは、オブジェクトが保存された直後に %Save() メソッドによって呼び出されます。このメソッドを使用すると、保存するオブジェクトのスコープ外のアクション (後で発生する通知アクションのキューなど) を実行できます。例えば、ある特定の金額以上の預金を使用している銀行が、顧客に預金規定の説明を送付する場合などです。
そのシグニチャは、以下のとおりです。
Method %OnAfterSave(insert as %Boolean)As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
保存されているオブジェクトが、エクステントに現在挿入されている場合は (1) を、既存のオブジェクトの更新の場合は (0) を示すフラグ。
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、%Save() は失敗して、最終的にトランザクションをロールバックします。
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnBeforeBuildIndices()
このクラス・メソッドは、%BuildIndices() メソッドが拡張ロックを取得した後 (要求されている場合)、インデックスの構築を開始する前に、%BuildIndices() メソッドによって呼び出されます。
そのシグニチャは、以下のとおりです。
ClassMethod %OnBeforeBuildIndices(ByRef indexlist As %String(MAXLEN="") = "") As %Status [ Abstract, Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
インデックス名の $List。このパラメータは参照によって渡されます。%OnBeforeBuildIndices() の実装でこの値を変更した場合、%BuildIndices() は変更された値を受け取ります。
%OnBeforePurgeIndices()
このクラス・メソッドは、%PurgeIndices() メソッドが動作を開始する前に、%PurgeIndices() メソッドによって呼び出されます。このメソッドがエラーを返した場合、%PurgeIndices() はインデックス構造を削除せずに、%PurgeIndices() の呼び出し元にエラーを返し、直ちに終了します。
そのシグニチャは、以下のとおりです。
ClassMethod %OnBeforePurgeIndices(ByRef indexlist As %String(MAXLEN="") = "") As %Status [ Abstract, Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
インデックス名の $List。このパラメータは参照によって渡されます。%OnBeforePurgeIndices() の実装でこの値を変更した場合、%PurgeIndices() は変更された値を受け取ります。
%OnBeforeSave()
このインスタンス・メソッドは、オブジェクトが保存される直前に %Save() メソッドによって呼び出されます。このメソッドを使用すると、アクションを完了してからインスタンスをディスクに保存する前に、ユーザに確認を求めることができるようになります。
%OnBeforeSave() で現在のオブジェクトを更新することは有効ではありません。保存する前にオブジェクトを修正する場合は、代わりに %OnAddToSaveSet() コールバックを実装し、そのメソッドにロジックを含めます。
そのシグニチャは、以下のとおりです。
Method %OnBeforeSave(insert as %Boolean) As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
保存されているオブジェクトが、エクステントに現在挿入されている場合は (1) を、既にエクステントの一部ある場合は (0) を示すフラグ。
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、保存が失敗します。
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnClose()
このインスタンス・メソッドは、オブジェクトが破棄される直前に呼び出されるので、ユーザはロック解除や一時的データ構造の削除などの補助項目の処理を実行する機会を得られます。
そのシグニチャは、以下のとおりです。
Method %OnClose() As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
このメソッドは %StatusOpens in a new tab コードを返しますが、この場合、失敗のステータスは単なる情報的なものであり、オブジェクトの破棄を阻止するものではありません。
%Library.RegisteredObjectOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnConstructClone()
このインスタンス・メソッドは、オブジェクトクローン化のためにオブジェクト構造が割り当てられ、すべてのデータがそこにコピーされた直後に、%ConstructClone() メソッドによって呼び出されます。このメソッドを使用して、ロックの取得や、クローンのプロパティ値のリセットなど、クローンのオブジェクトに関連する追加のアクションを実行できます。
そのシグニチャは、以下のとおりです。
Method %OnConstructClone(object As %RegisteredObject,
deep As %Boolean,
ByRef cloned As %String)
As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
クローン化されたオブジェクトの OREF。
クローン処理の “深さ”。0 では、クローンが関連するオブジェクトはオリジナルと同じものをポイントします。1 では、クローンされるオブジェクトに関連するオブジェクトもクローンされ、クローンは独自の関連オブジェクトを持つようになります。
使用法が %OnConstructClone() の呼び出し方によって変わる引数。詳細は、%Library.RegisteredObjectOpens in a new tab のクラス・ドキュメントを参照してください。
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、クローンは作成されません。
%Library.RegisteredObjectOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnDelete()
このクラス・メソッドは、オブジェクトが削除される直前に %Delete() または %DeleteId() メソッドによって呼び出されます。このメソッドは、オブジェクトを削除してもデータの整合性を破壊しないために使用されます。例えば、他のオブジェクトを含むように設計されたオブジェクトは、空になったときだけ削除されることを確実にします。
そのシグニチャは、以下のとおりです。
ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
削除されるオブジェクトに対するオブジェクト識別子。
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、削除は中止されます。
削除されるオブジェクトのプロパティにアクセスするには、渡される OID を ID に変換して、その ID を持つオブジェクトを開きます。以下に例を示します。
ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private, ServerOnly = 1 ]
{
set id = $$$oidPrimary(oid)
set obj = ..%OpenId(id)
write "Deleting object with name ", obj.Name, !
return 1
}
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnDeleteFinally()
このクラス・メソッドは、すべての処理の完了後、呼び出し元に戻る直前に %Delete() または %DeleteId() メソッドによって呼び出されます。%Delete() メソッドまたは %DeleteId() メソッドがトランザクションを開始していた場合、そのトランザクションはこのコールバックを呼び出す前に完了されます。このメソッドは値を返さず、メソッドを呼び出したメソッドの結果を変更することはできません。
そのシグニチャは、以下のとおりです。
ClassMethod %OnDeleteFinally(oid As %ObjectIdentity, status As %Status) [ ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
削除されるオブジェクトに対するオブジェクト識別子。
ユーザに報告されるステータス。このコールバック・メソッドでステータスを変更することはできません。
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnNew()
このインスタンス・メソッドは、オブジェクトに対するメモリが割り当てられ、プロパティが初期化されるときに、%New() メソッドによって呼び出されます。
そのシグニチャは、以下のとおりです。
Method %OnNew(initvalue As %String) As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
各要素の内容は以下のとおりです。
次のメモで説明するように、オーバーライドされない限り、オブジェクトの設定時にメソッドが使用する文字列。
%OnNew() の引数は、%New() の引数と一致する必要があります。このメソッドをカスタマイズする際、引数を %New() から受け取る変数およびタイプでオーバーライドします。例えば、%New() が、誕生日を示す dob および姓名を示す name の 2 つの引数を受け入れる場合、%OnNew() のシグニチャは、以下のようになります。
Method %OnNew(dob as %Date = "", name as %Name = "") as %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、オブジェクトの作成は中止されます。
例えば、インスタンスが Name プロパティの値を持つ必要があるクラスの場合、コールバックは、以下の形式のものになります。
Method %OnNew(initvalue As %String) As %Status
{
If initvalue="" Quit $$$ERROR($$$GeneralError,"Must supply a name")
Set ..Name=initvalue
Quit $$$OK
}
%Library.RegisteredObjectOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnOpen()
このインスタンス・メソッドは、オブジェクトがオープンされる直前に %Open() または %OpenId() メソッドによって呼び出されます。関連エンティティと比較したインスタンスの状態を確認できます。
そのシグニチャは、以下のとおりです。
Method %OnOpen() As %Status [ Private, ServerOnly = 1 ] {
// body of method here...
}
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、オブジェクトのオープンは中止されます。
%Library.PersistentOpens in a new tab および %SerialObjectOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnOpenFinally()
このクラス・メソッドは、すべての処理の完了後、呼び出し元に戻る直前に %Open() または %OpenId() メソッドによって呼び出されます。このメソッドは値を返さず、メソッドを呼び出したメソッドの結果を変更することはできません。
そのシグニチャは、以下のとおりです。
ClassMethod %OnOpenFinally(oid As %ObjectIdentity, status As %Status) [ ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
オープンされるオブジェクトのオブジェクト識別子。
ユーザに報告されるステータス。このコールバック・メソッドでステータスを変更することはできません。
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnReload()
このインスタンス・メソッドは、oid によって指定されたオブジェクトが再読み込みされたことを通知するために、%Reload メソッドによって呼び出されます。oid によって識別されるオブジェクトが既にメモリ内にある場合、%Open は %Reload を呼び出します。このメソッドがエラーを返す場合は、オブジェクトが開かれていません。
そのシグニチャは、以下のとおりです。
Method %OnReload() As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、ロールバック処理は中止されます。
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnRollBack()
既に SaveSet の一部として正常にシリアル化されているオブジェクトをロールバックするときに、InterSystems IRIS® データ・プラットフォームはこのインスタンス・メソッドを呼び出します ("オブジェクトの保存" を参照)。
永続オブジェクトまたはストリームの %Save() を呼び出したとき、またはシリアル・オブジェクトの %GetSwizzleObject() を呼び出したとき、システムは保存トランザクションを開始します。このトランザクションは、すべてのオブジェクトを SaveSet に含めます。%Save() が失敗すると (例えば、プロパティが検証に合格しなかったため)、InterSystems IRIS は、それまでに SaveSet の一部として正常にシリアル化しているオブジェクトをすべてロールバックします。つまり、それらのオブジェクトごとに、InterSystems IRIS は %RollBack() を呼び出すことになります。このメソッドは、%OnRollBack() を呼び出します。
InterSystems IRIS は、正常にシリアル化されていないオブジェクト (つまり、無効なオブジェクト) に対しては、このメソッドを呼び出しません。
%RollBack() は、そのオブジェクトのデータのディスク上の状態をトランザクション前の状態にリストアします。ただし、そのオブジェクトの ID 割り当てとは別に設定したプロパティのメモリ内の状態には効果がありません。(詳細は、"オブジェクトの保存" を参照してください。)メモリ内の変更を元に戻す場合は、%OnRollBack() でそのように実行します。
このメソッドのシグニチャは以下のとおりです。
Method %OnRollBack() As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、ロールバック処理は中止されます。
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnSaveFinally()
このクラス・メソッドは、すべての処理の完了後、呼び出し元に戻る直前に %Save() メソッドによって呼び出されます。%Save() メソッドがトランザクションを開始していた場合、そのトランザクションはこのコールバックを呼び出す前に完了されます。このメソッドは値を返さず、メソッドを呼び出したメソッドの結果を変更することはできません。
そのシグニチャは、以下のとおりです。
ClassMethod %OnSaveFinally(oref As %ObjectHandle, status As %Status) [ ServerOnly = 1 ]
{
// body of method here...
}
各項目の内容は次のとおりです。
保存されるオブジェクトのオブジェクト識別子。
ユーザに報告されるステータス。このコールバック・メソッドでステータスを変更することはできません。
%Library.PersistentOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnValidateObject()
このインスタンス・メソッドは、すべての検証が発生した直後に %ValidateObject() メソッドによって呼び出されます。このメソッドを使用することで、あるプロパティに対する有効な値が、他のプロパティの値によって変化する場合など、カスタムの検証を実行できます。
そのシグニチャは、以下のとおりです。
Method %OnValidateObject() As %Status [ Private, ServerOnly = 1 ]
{
// body of method here...
}
このメソッドは、%StatusOpens in a new tab コードを返します。失敗ステータスの場合、検証は失敗します。
%Library.RegisteredObjectOpens in a new tab のサブクラスには、このメソッドをオーバーライドするオプションがあります。
%OnDetermineClass()
%OnDetermineClass() クラス・メソッドは、そのオブジェクトの最も適切なタイプのクラスを返します。(最適なタイプのクラスの詳細は、"%ClassName() および最も適切なタイプのクラス (MSTC)" を参照してください。)%OnDetermineClass() は、既定のストレージ・クラスによって実装されます。カスタム・ストレージまたは SQL ストレージを使用する場合、このメソッドの既定の実装はありませんが、メソッドの実装は可能です。
そのシグニチャは、以下のとおりです。
ClassMethod %OnDetermineClass(
oid As %ObjectIdentity,
ByRef class As %String)
As %Status [ ServerOnly = 1 ]
各要素の内容は以下のとおりです。
オブジェクトのオブジェクト識別子。
oid で特定するインスタンスの最も適切なタイプのクラス。オブジェクトがクラスのインスタンスであり、さらにそのクラスのどのサブクラスのインスタンスにもなっていない場合、そのクラスはそのオブジェクトの最も適切なタイプのクラスとなります。
返り値は、成功または失敗を示す状態値です。
%Library.SwizzleObjectOpens in a new tab のサブクラスは、このメソッドをオーバーライドできます。
%OnDetermineClass() の呼び出し
%OnDetermineClass() は、以下の 2 つのいずれかの方法で呼び出すことができます。
Set status = ##class(APackage.AClass).%OnDetermineClass(myoid, .myclass)
Set status = myinstance.%OnDetermineClass(myoid, .myclass)
ここで、myoid は、最も適切なタイプのクラスを特定しようとしているオブジェクトであり、myclass は、特定されたクラスです。APackage.AClass はメソッドの呼び出し元のクラスであり、myinstance はメソッドの呼び出し元のインスタンスです。
この場合、メソッドは、myoid の最も適切なタイプのクラスを計算し、myclass をその値に等しくなるよう設定しています。myoid が現在のクラスのインスタンスではない場合、エラーが返されます。
%OnDetermineClass() を Sample.Person のサブクラスである Sample.Employee と共に使用する例を考えてみます。次の形の呼び出しがあり、
Set status = ##class(Sample.Employee).%OnDetermineClass(myoid, .class)
最も適切なタイプのクラスが Sample.Person であるオブジェクトを myoid が参照する場合、呼び出しはエラーを返します。
%OnDetermineClass() に対する呼び出し結果の例
MyPackage.Person クラスを MyPackage.Student クラスが拡張し、このクラスを MyPackage.GradStudent クラスが拡張するとします。以下に、%OnDetermineClass() を呼び出し、その最も適切なタイプのクラスが MyPackage.Student であるオブジェクトの OID を渡した結果を示します。
-
##class(MyPackage.Person).%OnDetermineClass(myOid,.myClass)
-
返り値 : $$$OK
-
myClass は、MyPackage.Student に設定されます。
-
-
##class(MyPackage.Student).%OnDetermineClass(myOid,.myClass)
-
返り値 : $$$OK
-
myClass は、MyPackage.Student に設定されます。
-
-
##class(MyPackage.GradStudent).%OnDetermineClass(myOid,.myClass)
-
返り値 : エラー・ステータス
-
myClass は、"" に設定されます。
-