エンティティは、データクラスのインスタンスとも解釈可能なオブジェクト です。テーブルのレコードがデータクラスとその割り当てられたデータストアに合致するのと似ています。しかしながら、エンティティはデータストアにリレートされたデータベースに相関するデータも格納しています。エンティティの目的はデータの管理(作成、更新、削除)です。エンティティセレクションを用いてエンティティ参照を取得したとき、参照にはエンティティセレクションについての情報も保持されるので、セレクションを繰り返し使用することが可能です。
データクラス内で新しいエンティティを作成する方法は二つあります:
エンティティはメモリ内にしか作成されないという点に注意してください。データストアに追加したい場合、entity.save( ) メソッドを呼ぶ必要があります。
エンティティ属性はエンティティオブジェクトのプロパティとして直接利用可能です。詳細な情報については、エンティティ属性を使用する を参照してください。
例えば、カレントデータストア内の"Employee" データクラスに新しいエンティティを作成し、firstname と name 属性に"John" と"Dupont" を割り当てたい場合を考えます:
C_OBJECT ($myEntity )
$myEntity :=ds .Employee.new ()
$myEntity .name:="Dupont"
$myEntity .firstname:="John"
$myEntity .save ()
注: エンティティはそれが作成されたプロセス内でのみ定義されます。ですから、例えばエンティティへの参照を、インタープロセス変数内に保存して他のプロセスで使用する、といったことはできません。
エンティティには、4D レコードへの参照が格納されています。異なるエンティティが同じ4D レコードを参照していることもあり得ます。また、エンティティは4D オブジェクト変数に保存可能であることから、異なる変数が同じテンティティへの参照を格納していることもあり得ます。
以下のコードを実行した場合:
C_OBJECT ($e1 ;$e2 )
$e1 :=ds .Employee.get (1)
$e2 :=$e1
$e1 .name:="Hammer"
これは以下のように図解することができます:
次に、以下のコードを実行した場合:
C_OBJECT ($e1 ;$e2 )
$e1 :=ds .Employee.get (1)
$e2 :=ds .Employee.get (1)
$e1 .name:="Hammer"
これは以下のように図解することができます:
ここで、エンティティは同じレコードを参照していることに注意してください。どちらの場合でも、entity.save( ) メソッドを呼び出した場合、レコードは更新されます(ただしレコードが他から変更があったなど衝突が発生した場合を除く、エンティティロッキング 参照)。
実際、$e1 も $e2 もエンティティそのものではなく、エンティティへの参照です。これはつまりどのようなファンクションやメソッドにも直接渡すことができ、ポインターのように振る舞います。そしてこれは4D ポインターよりもずっと高速です。例えば以下のようなコードがあり:
For each ($entity ;$selection )
do_Capitalize ($entity )
End for each
そしてファンクションが以下のような形であった場合:
$entity :=$1
$name :=$entity .lastname
If (Not ($name =Null ))
$name :=Uppercase (Substring ($name ;1;1))+Lowercase (Substring ($name ;2))
End if
$entity .lastname:=$name
この場合、エンティティは他の4Dのオブジェクトのように扱うことができ、引数としてその参照を渡すことができます。
注: エンティティでは、クラシックな4D 言語のような"カレントレコード"という概念はありません。エンティティは同時にいくつでも必要なだけ使用することができます。またエンティティには自動ロックの機構が備わっています(エンティティロッキング 参照)。エンティティが読み込まれるとき、"レイジーローディング"機構が使用されます。これはつまり必要な分の情報だけが読み込まれるということです。いずれにせよ、クライアント/サーバーではエンティティは必要であれば直接自動的に読み込むことも可能です。
エンティティ属性はデータとマップに対応するフィールドを対応するテーブルに保存します。ストレージ 型のエンティティ属性はエンティティオブジェクトの単純なプロパティとして設定や取得ができますが、リレートエンティティ 型とリレートエンティティズ 型のエンティティはエンティティあるいはエンティティセレクションを返します。
注: 属性の型についての詳細な情報については、ストレージ属性とリレーション属性 の段落を参照してください。
例えば、ストレージ属性を設定するためには:
$entity :=ds .Employee.get (1)
$name :=entity.lastname
entity.lastname:="Jones"
注: ピクチャー属性は与えられたパスではエンティティ内に割り当てることはできません。
リレートされた属性にアクセスできるかどうかは、属性の型によります。例えば、以下のようなストラクチャーがあるとき:
リレートされたオブジェクトを通してデータにアクセスすることができます:
$entity :=ds .Project.all ().first ().theClient
$EntitySel :=ds .Company.all ().first ().companyProjects
上記の例において、theClient and companyProjects はどちらもプライマリーリレーション属性であり、二つのデータクラス間の直接的なリレーションを表すことに注意してください。しかしながら、リレーション属性は、複数のレベルのリレーションを通したパスに基づいてビルドすることも可能です(循環参照含む)。例えば、以下のようなストラクチャーの場合を考えます:
それぞれのemployee はmanager にもなりえますし、manager を持つこともできます。あるemployee のmanager のmanager を取得したい場合、以下のように書くことができます:
$myEmp :=ds .Employee.get (50)
$manLev2 :=$myEmp .manager.manager.lastname
ORDA アーキテクチャーでは、リレーション属性はエンティティにリレートされたデータを直接格納することができます:
N対1型リレーション属性(リレートエンティティ 型)はエンティティを格納します。 1対N型リレーション属性(リレートエンティティズ 型)はエンティティセレクションを格納します。 以下の(単純化された)ストラクチャーを見てみましょう:
この例では、"Employee" データクラスのエンティティにはエンティティ型のオブジェクト(あるいはnull値)が"employer" 属性内に格納されています。""Company" データクラスのエンティティにはエンティティセレクション型のオブジェクト(あるいはnull値)が"staff" 属性内に格納されています。
注: ORDAでは、リレーションの自動あるいは手動プロパティは何の効力も持ちません。
"employer" 属性に直接値を割り当てたい場合には、"Company" データクラスからの既存のエンティティを渡す必要があります。例:
$emp :=ds .Employee.new ()
$emp .lastname:="Smith"
$emp .employer:=ds .Company.query ("name =:1";"4D")[0]
$emp .save ()
4D では"1"エンティティにリレートされているN エンティティにリレーション属性を入力するのを容易にするための追加の機能があります。リレーション属性に値を割り当てる際に、"1" エンティティのプライマリーキーを直接渡します。これが動作するためには数値あるいはテキスト型のデータ(プライマリーキー値)をリレーション属性に渡します。すると4D はデータクラス内の対応するエンティティを自動的に検索してくれます。例:
$emp :=ds .Employee.new ()
$emp .lastname:="Wesson"
$emp .employer:=2
$emp .save ()
これは特に、リレーショナルデータベースから大量のデータを読み込む時に有用です。このような読み込みでは通常"ID" カラムが格納されており、これはリレーション属性に直接割り当て可能なプライマリーキーを参照しているからです。 これはまた1 データストアクラス側で対応するエンティティを事前に作成することなくN エンティティ側のプライマリーキーを割り当てることができるということです。リレートされているデータクラスに存在しないプライマリーキーを割り当てた場合、それは自動的に保管され、"1" エンティティ側で作成されたときに自動的に4D によって自動的に割り当てられます。
"1"にリレートされたエンティティ属性の値を、"N"データクラスから、リレートされた属性を通して直接割り当て・変更することができます。例えば、リレートされたEmployee エンティティのCompany エンティティのname 属性を変更したい場合、以下のように書くことができます:
$emp :=ds .Employee.get (2)
$emp .employer.name:="4D, Inc."
$emp .employer.save ()
エンティティオブジェクト自身はオブジェクトとしてコピーすることはできません:
$myentity :=OB Copy (ds .Employee.get (1))
しかしながら、エンティティプロパティは取得可能です:
ARRAY TEXT ($prop ;0)
OB GET PROPERTY NAMES (ds .Employee.get (1);$prop )
書き出しのために、entity.toObject( ) メソッドを使用することでエンティティを標準のオブジェクトへと変換することができます。そのあとでエンティティをJSON として書き出すことができます。例:
C_OBJECT ($entity_json )
$entity_json :=JSON Stringify ($myentity .toObject ())