ObjectGrid は、任意の数の論理エンティティー・スキーマを持つことができます。 エンティティーは、アノテーション付き Java クラス、XML、または XML と Java クラスの組み合わせを使用して定義されます。 定義されたエンティティーは、eXtreme Scale サーバーに登録され、BackingMap、索引、およびその他のプラグインにバインドされます。
ローカル eXtreme Scale 構成
ローカル ObjectGrid 構成を使用している場合は、エンティティー・スキーマをプログラマチックに構成できます。 このモードでは、ObjectGrid.registerEntities メソッドを使用して、アノテーション付きエンティティー・クラスまたはエンティティー・メタデータ記述子ファイルを登録することができます。分散 eXtreme Scale 構成
分散 eXtreme Scale 構成を使用している場合は、エンティティー・スキーマを含むエンティティー・メタデータ記述子ファイルを指定する必要があります。詳しくは、分散環境におけるエンティティー・マネージャーを参照してください。
エンティティー・メタデータは、Java クラス・ファイル、エンティティー記述子 XML ファイル、またはその両方を使用して構成します。 エンティティーに関連付ける eXtreme Scale BackingMap を識別するには、少なくとも、エンティティー記述子 XML が必要です。 アノテーション付き Java クラス (エンティティー・メタデータ・クラス) またはエンティティー記述子 XML ファイルで、 エンティティーの永続属性および他のエンティティーとのリレーションシップを記述します。 エンティティー・メタデータ・クラスを指定すると、そのクラスは、EntityManager API がグリッド内のデータと対話するためにも使用されます。
eXtreme Scale グリッドは、エンティティー・クラスを指定せずに定義できます。 サーバーとクライアントが、基盤マップに保管されたタプル・データと直接対話する場合に、これは役立つことがあります。 このようなエンティティーは、エンティティー記述子 XML ファイルで完全に定義され、クラスレス・エンティティーと呼ばれます。
クラスレス・エンティティーは、サーバーまたはクライアントのクラスパスにアプリケーション・クラスを含めることができない場合に、役立ちます。 このようなエンティティーは、エンティティー・メタデータ記述子 XML ファイルに定義されます。 このファイルで、クラスレス・エンティティー ID を使用して (形式は、「@<エンティティー ID>」)、エンティティーのクラス名を指定します。 @ 記号は、エンティティーをクラスレスとして識別し、エンティティー間の関連をマップするために使用されます。 2 つのクラスレス・エンティティーが定義されたエンティティー・メタデータ記述子 XML ファイルの例として、「クラスレス・エンティティー・メタデータ」の図を参照してください。
eXtreme Scale サーバーまたはクライアントがクラスに対するアクセス権限を備えていない場合でも、 クラスレス・エンティティーを使用して、EntityManager API を使用できます。 一般的なユース・ケースには、以下のものがあります。
クライアントとサーバー間でエンティティー・メタデータに互換性がある場合には、 エンティティー・メタデータ・クラス、XML ファイル、またはその両方を使用して、エンティティー・メタデータを作成できます。
例えば、下図の「プログラマチック・エンティティー・クラス」は、次のセクションのクラスレス・メタデータ・コードと互換性があります。
プログラマチック・エンティティー・クラス
@Entity
public class Employee {
@Id long serialNumber;
@Basic byte[] picture;
@Version int ver;
@ManyToOne(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
Department department;
}
@Entity
public static class Department {
@Id int number;
@Basic String name;
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="department")
Collection<Employee> employees;
}
前述のとおり、クラスレス・エンティティーは、エンティティー XML 記述子ファイルで完全に構成されます。 クラス・ベースのエンティティーは、Java フィールド、プロパティー、およびアノテーションを使用して属性を定義します。 そのため、クラスレス・エンティティーは、<basic> タグおよび <id> タグを使用して、 エンティティー XML 記述子でキーおよび属性構造を定義する必要があります。
クラスレス・エンティティー・メタデータ
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://ibm.com/ws/projector/config/emd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ibm.com/ws/projector/config/emd ./emd.xsd">
<entity class-name="@Employee" name="Employee">
<attributes>
<id name="serialNumber" type="long"/>
<basic name="firstName" type="java.lang.String"/>
<basic name="picture" type="[B"/>
<version name="ver" type="int"/>
<many-to-one
name="department"
target-entity="@Department"
fetch="EAGER"">
<cascade><cascade-persist/></cascade>
</many-to-one>
</attributes>
</entity>
<entity class-name="@Department" name="Department" >
<attributes>
<id name="number" type="int"/>
<basic name="name" type="java.lang.String"/>
<version name="ver" type="int"/>
<one-to-many
name="employees"
target-entity="@Employee"
fetch="LAZY"
mapped-by="department">
<cascade><cascade-all/></cascade>
</one-to-many>
</attributes>
</entity>
上記の各エンティティーに <id> エレメントが含まれていることに注意してください。 クラスレス・エンティティーには、1 つ以上の <id> エレメントを定義するか、エンティティーのキーを表す単一値のアソシエーションを指定する必要があります。 エンティティーのフィールドは、<basic> エレメントによって表されます。 クラスレス・エンティティーでは、<id>、<version>、および <basic> の各エレメントには名前および型が必要です。 サポートされる型の詳細については、以下のサポートされる属性型のセクションを参照してください。
エンティティーのパーシスタント状態は、フィールド (インスタンス変数) を使用するか、Enterprise JavaBeans スタイルのプロパティー・アクセサーを使用して、クライアントおよびエンティティー・マネージャーによってアクセスされます。各エンティティーは、フィールドまたはプロパティー・ベースのいずれかのアクセスを定義する必要があります。 アノテーション付きエンティティーは、クラス・フィールドがアノテーション付きの場合はフィールド・アクセスとなり、プロパティーの getter メソッドがアノテーション付きである場合はプロパティー・アクセスとなります。フィールド・アクセスとプロパティー・アクセスを混在させることはできません。タイプを自動的に判別できない場合は、@Entity アノテーションまたは同等の XML で accessType 属性を使用してアクセス・タイプを識別できます。
シリアライズ可能な属性は、 エンティティー記述子 XML ファイルで、オブジェクトのクラス名を使用して表されます。 オブジェクトが配列である場合には、データ型は Java 内部形式を使用して表されます。 例えば、属性データ型が java.lang.Byte[][] である場合には、ストリング表現は [[Ljava.lang.Byte; になります。
ユーザー・シリアライズ可能型は、以下のベスト・プラクティスに従っている必要があります。
eXtreme Scale グリッドはデータ・キャッシュであり、データベースとは異なり、参照保全性を実施しません。 リレーションシップでは子エンティティーに対して永続化操作および除去操作をカスケードすることができますが、オブジェクトとのリンク切れを検出または引き起こすことはありません。子オブジェクトを除去する場合は、そのオブジェクトへの参照を親から除去する必要があります。
2 つのエンティティー間の双方向アソシエーションを定義する場合、リレーションシップの所有者を識別する必要があります。対多アソシエーションでは、 リレーションシップの多側は常に所有側になります。 所有権を自動的に判別できない場合、アノテーションの mappedBy 属性、または XML におけるそれと同等な属性を指定する必要があります。mappedBy 属性は、リレーションシップの所有者であるターゲット・エンティティー内のフィールドを識別します。この属性は、型と基数が同じである複数の属性が存在する場合に、関連するフィールドを識別するのにも役立ちます。単一値アソシエーション
1 対 1 および多対 1 のアソシエーションは、@OneToOne および @ManyToOne アノテーションまたはそれと等価な XML 属性を使用して示されます。ターゲット・エンティティーの型は、属性の型によって決定されます。以下の例では、Person と Address の間に単一方向アソシエーションを定義しています。 Customer エンティティーは、1 つの Address エンティティーへの参照を持っています。この場合、逆のリレーションシップがないため、アソシエーションを多対 1 にすることもできます。@Entity
public class Customer {
@Id id;
@OneToOne Address homeAddress;
}
@Entity
public class Address{
@Id id
@Basic String city;
}
Customer クラスと Address クラスの間の双方向リレーションシップを指定するには、
Address クラスから Customer クラスへの参照を追加し、適切なアノテーションを追加して、リレーションシップの反対側にマークを付けます。
このアソシエーションは 1 対 1 であるため、@OneToOne アノテーションで mappedBy 属性を使用してリレーションシップの所有者を指定する必要があります。
@Entity
public class Address{
@Id id
@Basic String city;
@OneToOne(mappedBy="homeAddress") Customer customer;
}
コレクション値アソシエーション
1 対多および多対多のアソシエーションは、@OneToMany および @ManyToMany アノテーションまたはそれと等価な XML 属性を使用して示されます。多くのリレーションシップはすべて、java.util.Collection、java.util.List、または java.util.Set という型を使用して表されます。 ターゲット・エンティティーの型は、Collection、List、または Set という汎用型によって決定されるか、@OneToMany または @ManyToMany アノテーションの targetEntity 属性 (またはそれと等価な XML での属性) を使用して明示的に決定されます。@Entity
public class Customer {
@Id id;
@ManyToOne Address homeAddress;
@ManyToOne Address workAddress;
}
@Entity
public class Address{
@Id id
@Basic String city;
@OneToMany(mappedBy="homeAddress") Collection<Customer> homeCustomers;
@OneToMany(mappedBy="workAddress", targetEntity=Customer.class)
Collection workCustomers;
}
この例では、同じエンティティー間に「自宅アドレス」リレーションシップと「勤務先アドレス」リレーションシップという 2 つの異なるリレーションシップが存在します。workCustomers 属性に非汎用型の Collection が使用されているのは、
汎用型を使用できない場合に targetEntity 属性を使用する方法を示すためです。クラスレス・アソシエーション
クラスレス・エンティティー・アソシエーションは、クラス・ベース・アソシエーションの定義方法と同じようなエンティティー・メタデータ記述子 XML ファイルで定義されます。 唯一の違いは、ターゲット・エンティティーが実際のクラスを指すのではなく、 エンティティーのクラス名で使用されるクラスレス・エンティティー ID を指すという点です。
次に例を挙げます。
<many-to-one name="department" target-entity="@Department" fetch="EAGER">
<cascade><cascade-all/></cascade>
</many-to-one>
<one-to-many name="employees" target-entity="@Employee" fetch="LAZY">
<cascade><cascade-all/></cascade>
</one-to-many>
@Entity
@IdClass(CustomerKey.class)
public class Customer {
@Id @ManyToOne Zone zone;
@Id int custId;
String name;
...
}
@Entity
public class Zone{
@Id String zoneCode;
String name;
}
public class CustomerKey {
Zone zone;
int custId;
public int hashCode() {...}
public boolean equals(Object o) {...}
}
クラスレス 1 次キー
クラスレス・エンティティーは、XML ファイルで属性 id=true を指定した、少なくとも 1 つの <id> エレメントまたはアソシエーションを持つ必要があります。 両方の例は、以下のようになります。
<id name="serialNumber" type="int"/>
<many-to-one name="department" target-entity="@Department" id="true">
<cascade><cascade-all/></cascade>
</many-to-one>
プロキシーおよびフィールド・インターセプターを使用すると、エンティティー・マネージャーがエンティティーの状態を追跡して、エンティティーが変更されたかどうかを判別し、パフォーマンスを改善できるようになります。フィールド・インターセプターは、エンティティー・インスツルメンテーション・エージェントの構成時に、Java SE 5 プラットフォームでのみ使用できます。