データ操作
ORDA では、エンティティ および エンティティセレクション を介してデータにアクセスします。 これらのオブジェクトを使って、データストアのデータを作成・更新・クエリ・ソートすることができます。
エンティティの作成
データクラス内に新しいエンティティを作成する方法は二つあります:
- エンティティはデータベースレコードへの参照であるため、まず 4Dランゲージを使用してレコードを作成し、その後
entity.next()
やentitySelection.first()
といった ORDA関数を介して、それをエンティティとして参照できます。 - また、
dataClass.new()
関数を使用してエンティティを作成することもできます。
エンティティはメモリ内にしか作成されないという点に注意してください。 データストアに追加したい場合、entity.save()
関数を呼ぶ必要があります。
エンティティ属性は、エンティティオブジェクトのプロパティとして直接利用可能です。 詳細な情報については、エンティティ属性の使用 を参照してください。
たとえば、カレントデータストア内の "Employee" データクラスに新しいエンティティを作成し、firstname と name 属性に "John" と "Dupont" を割り当てたい場合を考えます:
var $myEntity : cs.EmployeeEntity
$myEntity:=ds.Employee.new() // エンティティ型の新規オブジェクトを作成します
$myEntity.name:="Dupont" // 'Dupont' を 'name' 属性に代入します
$myEntity.firstname:="John" // 'John' を 'firstname' 属性に代入します
$myEntity.save() // エンティティを保存します
エンティティは、それが作成されたプロセス内でのみ定義されます。 そのため、たとえばエンティティへの参照を、インタープロセス変数内に保存して他のプロセスで使用する、といったことはできません。
エンティティと参照
エンティティには、4Dレコードへの参照が格納されています。 異なるエンティティが同じ 4Dレコードを参照することもあり得ます。 また、エンティティは 4Dオブジェクト変数に保存可能であることから、異なる変数が同じエンティティへの参照を格納していることもあり得ます。
以下のコードを実行した場合:
var $e1; $e2 : cs.EmployeeEntity
$e1:=ds.Employee.get(1) // ID 1をもつ社員にアクセスします
$e2:=$e1
$e1.name:="Hammer"
// $e1 も $e2 も、どちらも同じエンティティへの参照を共有します
// $e2.name の中身も "Hammer" です
If($e1=$e2) // True
これは以下のように図解することができます:
次に、以下のコードを実行した場合:
var $e1; $e2 : cs.EmployeeEntity
$e1:=ds.Employee.get(1)
$e2:=ds.Employee.get(1)
$e1.name:="Hammer"
//変数 $e1 はエンティティへの参照を格納しています
//変数 $e2 は別のエンティティへの参照を格納しています
//$e2.name の中身は "smith" です
If($e1=$e2) //False
これは以下のように図解することができます:
しかし、両方のエンティティが同じレコードを参照していることに注意してください。 どちらの場合でも、entity.save()
メソッドを呼び出した場合、レコードは更新されます (衝突が発生した場合を除きます。エンティティロッキング 参照)。
実際には、$e1
も $e2
もエンティティそのものではなく、エンティティへの参照です。 これはつまり、どのような関数やメソッドにも直接受け渡すことができ、ポインターのように振る舞うということです。そしてこれは 4Dポインターよりもずっと高速です。 例:
For each($entity;$selection)
do_Capitalize($entity)
End for each
そして do_Capitalize メソッドが以下のような形であった場合:
$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ランゲージのような "カレントレコード" という概念はありません。 エンティティは、いくつでも必要な数を同時に使用することができます。 また、エンティティには自動ロックの機構が備わっています (エンティティロッキング 参照)。 エンティティの読み込みには、レイジーローディング 機構が使用されます。これはつまり必要な分の情報だけが読み込まれるということです。 いずれにせよ、クライアント/サーバーでは必要であればエンティティを直接自動的に読み込むことも可能です。
エンティティ属性の使用
エンティティ属性はデータを保存し、対応するテーブルの対応するフィールドをマップします。
- kind が storage の属性は、エンティ ティオブジェクトの単純なプロパティとして設定または取得できます。
- kind が relatedEntity の属性はエンティティを返します。
- kind が relatedEntities の属性はエンティティセレクションを返します。
- kind が computed または alias の属性は、その定義次第であらゆるタイプのデータを返すことができます。
属性の型についての詳細な情報については、ストレージ属性とリレーション属性 の段落を参照してください。
たとえば、文字列型のストレージ属性を取得・設定するためには:
$entity:=ds.Employee.get(1) // ID1 の社員エンティティを取得します
$name:=$entity.lastname // 社員のラストネームを取得 します。 例: "Smith"
$entity.lastname:="Jones" // 社員のラストネームを変更します
$entity.save() // 変更を保存します
データベースの BLOBフィールド (スカラーBLOB) は、ORDAで扱われるにあたって、BLOBオブジェクト属性 (
4D.Blob
) に自動変換されます。 BLOBオブジェクト属性を保存する際には、(利用可能なメモリによってのみサイズ制限される BLOBオブジェクトとは異なり) BLOBフィールドのサイズが 2GB に制限されることに注意してください。
リレート属性にアクセスできるかどうかは、属性の型によります。 たとえば、以下のようなストラクチャーがあるとき:
リレートされたオブジェクトを通してデータにアクセスすることができます:
$entity:=ds.Project.all().first().theClient // 先頭プロジェクトに関連する Company エンティティを取得します
$EntitySel:=ds.Company.all().first().companyProjects // 先頭の会社に関連する Project エンティティセレクションを取得します
上記の例において、theClient と companyProjects はどちらもプライマリーリレーション属性であり、二つのデータクラス間の直接的なリレーションを表すことに注意してください。 しかしながら、複数のレベルのリレーションを通したパスに基づいてリレーション属性をビルドすることも可能です(循環参照含む)。 たとえば、以下のようなストラクチャーの場合を考えます:
社員はそれぞれマネージャーにもなりえますし、マネージャーを持つこともできます。 ある社員のマネージャーのマネージャーを取得したい場合、以下のように書くことができます:
$myEmp:=ds.Employee.get(50)
$manLev2:=$myEmp.manager.manager.lastname
ピクチャーまたは Blob属性にファイルを代入する
ピクチャー属性には画像を格納することができます。同様に、任意のバイナリデータを Blob属性に格納することができま す。
ORDA を使って属性に代入できるのは、データそのもの、つまり画像や Blobオブジェクト、またはデータを格納する ファイルへの参照 のいずれかです。 この場合、エンティティにはファイルパスのみが保存されます。
この機能により、同じ画像を複製せずに複数のエンティティで利用できるほか、好きなようにファイルを整理したり、4D の外でファイルを使用したりできます。 また、データファイルのサイズを管理するのにも役立ちます。
ファイルの参照として使用できるのは以下のいずれかです:
- 4D.File オブジェクト
- POSIX 形式のパス
例:
Function createCompany($name : Text; $logo : 4D.File)
var $company : cs.CompanyEntity
$company:=ds.Company.new()
$company.name:=$name
// ファイルオブジェクトを使った代入
$company.logo:=$logo
// パスを使った代入
$company.datablob:="/RESOURCES/"+$name+"/data.bin"
$company.save()
属性への代入がどのようにされたか (データそのもの、またはファイルの参照) にかかわらず、属性に対する読み取りアクセスはユーザーにとって透過的です。
代入時にファイルがディスク上に存在する必要はありません (この場合にエラーは返されません)。 属性の読み取り時に参照されたファイルが見つからない場合には、null値が返されます。
4D は画像やデータをローカルキャッシュに読み込みます。 読み込み後に参照ファイルが変更された場合、アプリケーションで変更を反映するにはファイルを再代入する必要があります。
ファイル参照の代入はローカルモード (4D Server または 4Dシングルユーザー) でのみサポートされています。 リモートで、または RESTリクエストを介して代入を行うと、エラーが生成されます。