ここは旧式の4DドキュメントWebサイトです。最新のアップデートされたドキュメントを読むには新サイトをご利用下さい→ developer.4d.com

ホーム

 
4D v19
エンティティ

エンティティ  


 

 

エンティティは、データクラスのインスタンスとも解釈可能なオブジェクトです。テーブルのレコードがデータクラスとその割り当てられたデータストアに合致するのと似ています。しかしながら、エンティティはデータストアにリレートされたデータベースに相関するデータも格納しています。エンティティの目的はデータの管理(作成、更新、削除)です。エンティティセレクションを用いてエンティティ参照を取得したとき、参照にはエンティティセレクションについての情報も保持されるので、セレクションを繰り返し使用することが可能です。

データクラス内で新しいエンティティを作成する方法は二つあります:

  • エンティティはデータベースレコードへの参照ですので、"クラシックな"4D ランゲージを使用してレコードを作成し、それをentity.next( )entitySelection.first( )といったORDA メソッドで参照することでエンティティを作成できます。
  • また、dataClass.new( ) メソッドを使用することでもどんなエンティティも作成することができます。

エンティティはメモリ内にしか作成されないという点に注意してください。データストアに追加したい場合、entity.save( ) メソッドを呼ぶ必要があります。

エンティティ属性はエンティティオブジェクトのプロパティとして直接利用可能です。詳細な情報については、エンティティ属性を使用する を参照してください。

例えば、カレントデータストア内の"Employee" データクラスに新しいエンティティを作成し、firstname と name 属性に"John" と"Dupont" を割り当てたい場合を考えます:

 C_OBJECT($myEntity)
 $myEntity:=ds.Employee.new() // エンティティ型の新しいオブジェクトを作成
 $myEntity.name:="Dupont" //  'Dupont' を'name' 属性に割り当て
 $myEntity.firstname:="John" // 'John' を'firstname' 属性に割り当て
 $myEntity.save() // エンティティを保存

注: エンティティはそれが作成されたプロセス内でのみ定義されます。ですから、例えばエンティティへの参照を、インタープロセス変数内に保存して他のプロセスで使用する、といったことはできません。

エンティティには、4D レコードへの参照が格納されています。異なるエンティティが同じ4D レコードを参照していることもあり得ます。また、エンティティは4D オブジェクト変数に保存可能であることから、異なる変数が同じテンティティへの参照を格納していることもあり得ます。

以下のコードを実行した場合:

 C_OBJECT($e1;$e2)
 $e1:=ds.Employee.get(1) //ID 1をもつemployee にアクセス
 $e2:=$e1
 $e1.name:="Hammer"
  //$e1 も $e2 も、どちらも同じエンティティへの参照を共有する
  //$e2.name の中身は "Hammer"

これは以下のように図解することができます:

次に、以下のコードを実行した場合:

 C_OBJECT($e1;$e2)
 $e1:=ds.Employee.get(1)
 $e2:=ds.Employee.get(1)
 $e1.name:="Hammer"
  //変数 $e1 はエンティティへの参照を格納している
  //変数 $e2 は別のエンティティへの参照を格納している
  //$e2.name の中身は "smith"

これは以下のように図解することができます:

ここで、エンティティは同じレコードを参照していることに注意してください。どちらの場合でも、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) // employee 属性からID 1 のものを取得
 $name:=entity.lastname // employee から名前を取得。例: "Smith"
 entity.lastname:="Jones" // employee の名前を設定

注: ピクチャー属性は与えられたパスではエンティティ内に割り当てることはできません。

リレートされた属性にアクセスできるかどうかは、属性の型によります。例えば、以下のようなストラクチャーがあるとき:

リレートされたオブジェクトを通してデータにアクセスすることができます:

 $entity:=ds.Project.all().first().theClient // プロジェクトに割り当てられたCompany entity を取得
 $EntitySel:=ds.Company.all().first().companyProjects // Company のproject のセレクションを取得

上記の例において、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() // 新規employee を作成
 $emp.lastname:="Smith" // 属性に値を割り当て
 $emp.employer:=ds.Company.query("name =:1";"4D")[0]  // company エンティティを割り当て
 $emp.save()

4D では"1"エンティティにリレートされているN エンティティにリレーション属性を入力するのを容易にするための追加の機能があります。リレーション属性に値を割り当てる際に、"1" エンティティのプライマリーキーを直接渡します。これが動作するためには数値あるいはテキスト型のデータ(プライマリーキー値)をリレーション属性に渡します。すると4D はデータクラス内の対応するエンティティを自動的に検索してくれます。例:

 $emp:=ds.Employee.new()
 $emp.lastname:="Wesson"
 $emp.employer:=2 // リレーション属性にプライマリーキー属性を割り当て
  //4D はプライマリーキー(この場合、ID)の値が2であるcompany を検索し、
  //それをemployee に割り当て
 $emp.save()

これは特に、リレーショナルデータベースから大量のデータを読み込む時に有用です。このような読み込みでは通常"ID" カラムが格納されており、これはリレーション属性に直接割り当て可能なプライマリーキーを参照しているからです。
これはまた1 データストアクラス側で対応するエンティティを事前に作成することなくN エンティティ側のプライマリーキーを割り当てることができるということです。リレートされているデータクラスに存在しないプライマリーキーを割り当てた場合、それは自動的に保管され、"1" エンティティ側で作成されたときに自動的に4D によって自動的に割り当てられます。

"1"にリレートされたエンティティ属性の値を、"N"データクラスから、リレートされた属性を通して直接割り当て・変更することができます。例えば、リレートされたEmployee エンティティのCompany エンティティのname 属性を変更したい場合、以下のように書くことができます:

 $emp:=ds.Employee.get(2) // プライマリーキー値が2のEmployee エンティティを読み込む
 $emp.employer.name:="4D, Inc." // リレートされたCompany のname 属性を変更
 $emp.employer.save() // リレートされた属性を保存
  //リレートされたエンティティは更新される

エンティティオブジェクト自身はオブジェクトとしてコピーすることはできません:

 $myentity:=OB Copy(ds.Employee.get(1)) // null を返す

しかしながら、エンティティプロパティは取得可能です:

 ARRAY TEXT($prop;0)
 OB GET PROPERTY NAMES(ds.Employee.get(1);$prop)
  //$prop にはエンティティ属性の全ての名前が格納される

書き出しのために、entity.toObject( ) メソッドを使用することでエンティティを標準のオブジェクトへと変換することができます。そのあとでエンティティをJSON として書き出すことができます。例:

 C_OBJECT($entity_json)
 $entity_json:=JSON Stringify($myentity.toObject()) // エンティティをJSON として返す



参照 

エンティティロッキング

 
プロパティ 

プロダクト: 4D
テーマ: ORDA

 
ページの目次 
 
履歴 

初出: 4D v17

 
ARTICLE USAGE

デザインリファレンス ( 4D v19)