Oracle Containers for J2EE Enterprise JavaBeans開発者ガイド 10g(10.1.3.1.0) B31852-03 |
|
この章では、JPAエンティティを使用するために構成できる様々なオプションについて説明します。
表7-1に、これらのオプションをリストし、基本オプション(ほとんどのアプリケーションに適用可能)であるか拡張オプション(より特殊なアプリケーションに適用可能)であるかを示します。
詳細は、次を参照してください。
オプション | タイプ |
---|---|
基本 |
|
基本 |
|
基本 |
|
基本 |
|
拡張 |
|
拡張 |
|
基本 |
|
基本 |
|
基本 |
|
基本 |
|
拡張 |
|
拡張 |
|
基本 |
|
拡張 |
|
基本 |
|
拡張 |
|
拡張 |
すべてのJPAエンティティには主キーが必要です。
主キーは単一のプリミティブ型またはJDKオブジェクト型のエンティティ・フィールドとして指定できます(「JPAエンティティの単純な主キー・フィールドの構成」を参照)。
個別のコンポジット主キー・クラスを使用して、1つ以上のプリミティブ型またはJDKオブジェクト型から構成されるコンポジット主キーを指定できます(「JPAエンティティのコンポジット主キー・クラスの構成」を参照)。
主キー値を自分で割り当てるか、主キー値ジェネレータに主キー・フィールドを関連付けることができます(「JPAエンティティの自動主キー生成の構成」を参照)。
最も単純な主キーは、単一のプリミティブ型またはJDKオブジェクト型のエンティティ・フィールドとして指定する主キーです(「アノテーションの使用方法」を参照)。
例7-1に、@Id
アノテーションを使用してエンティティ・フィールドを主キーとして指定する方法を示します。この例では、主キー値は表ジェネレータを使用して生成されています
(「JPAエンティティの自動主キー生成の構成」を参照)。
@Id(generate=TABLE, generator="ADDRESS_TABLE_GENERATOR")
@TableGenerator(
name="ADDRESS_TABLE_GENERATOR",
tableName="EMPLOYEE_GENERATOR_TABLE",
pkColumnValue="ADDRESS_SEQ"
)
@Column(name="ADDRESS_ID")
public Integer getId() {
return id;
}
コンポジット主キーは、通常、2つ以上のプリミティブ型またはJDKオブジェクト型から構成されます。一般的に、コンポジット主キーが割り当てられるのは、データベース・キーが複数の列から構成されるレガシー・データベースからマッピングを行う場合です。このようなコンポジット主キーは、個別のコンポジット主キー・クラスを使用して指定できます(「アノテーションの使用方法」を参照)。
コンポジット主キー・クラスには、次の特性があります。
equals
およびhashCode
メソッドを定義する必要があります。これらのメソッドにおける値の等価性のセマンティクスは、キーがマップされるデータベース・タイプのデータベースの等価性と一致している必要があります。
コンポジット主キー・クラスは、エンティティ・クラスに所有される埋込みクラスとするか、エンティティ・クラスの複数のフィールドまたはプロパティにマップされるフィールドを持つ非埋込みクラスとすることが可能です。非埋込みクラスの場合、コンポジット主キー・クラスの主キー・フィールドまたはプロパティの名前とエンティティ・クラスの主キー・フィールドまたはプロパティの名前は一致する必要があり、それらの型も同じである必要があります。
例7-2に、典型的な埋込み可能コンポジット主キー・クラスを示します。また、例7-3に、@EmbeddedId
アノテーションを使用してこの埋込みコンポジット主キー・クラスでJPAエンティティを構成する方法を示します。
@Embeddable
public class EmployeePK implements Serializable {
private String name;
private long id;
public EmployeePK() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int hashCode() {
return (int) name.hashCode() + id;
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof EmployeePK)) return false;
if (obj == null) return false;
EmployeePK pk = (EmployeePK) obj;
return pk.id == id && pk.name.equals(name);
}
}
例7-3 埋込みコンポジット主キー・クラスを使用したJPAエンティティ
@Entity
public class Employee implements Serializable {
EmployeePK primaryKey;
public Employee() {
}
@EmbeddedId
public EmployeePK getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(EmployeePK pk) {
primaryKey = pk;
}
...
}
例7-4に、非埋込みコンポジット主キー・クラスを示します。
このクラスのempName
およびbirthDay
フィールドは、その名前と型がエンティティ・クラスのプロパティに一致している必要があります。
例7-5に、@IdClass
アノテーションを使用してこの非埋込みコンポジット主キー・クラスでJPAエンティティを構成する方法を示します。
エンティティ・クラスのempName
およびbirthDay
フィールドは主キーで使用されるため、それらに@Id
アノテーションを付ける必要もあります。
public class EmployeePK implements Serializable {
private String empName;
private Date birthDay;
public EmployeePK() {
}
public String getName() {
return empName;
}
public void setName(String name) {
empName = name;
}
public long getDateOfBirth() {
return birthDay;
}
public void setDateOfBirth(Date date) {
birthDay = date;
}
public int hashCode() {
return (int) empName.hashCode();
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof EmployeePK)) return false;
if (obj == null) return false;
EmployeePK pk = (EmployeePK) obj;
return pk.birthDay == birthDay && pk.empName.equals(empName);
}
}
例7-5 マップ済のコンポジット主キー・クラスを使用したJPAエンティティ
@IdClass(EmployeePK.class)
@Entity
public class Employee {
@Id String empName;
@Id Date birthDay;
...
}
通常は、主キー・フィールド(「JPAエンティティの単純な主キー・フィールドの構成」を参照)を主キー値ジェネレータに関連付けて、エンティティ・インスタンスが作成されたときに新しい一意の主キー値が自動的に割り当てられるようにします。
表7-2に、定義できる主キー値ジェネレータのタイプをリストします。
例7-6に、@TableGenerator
アノテーションを使用してデータベース表に基づいて主キー値ジェネレータを指定する方法を示します。TopLink JPA永続性プロバイダは、デプロイ時にこの表の作成を試行します。JPA永続性プロバイダで作成できない場合は、データベース・ドキュメントに従って、デプロイ前にこの表が存在していることを確認する必要があります。Address
の新規インスタンスが作成されると、エンティティ・フィールドid
の新しい値がADDRESS_GENERATOR_TABLE
から取得されます。この場合は、@GeneratedValue
アノテーションの属性strategy
をTABLE
に設定し、generator
をADDRESS_TABLE_GENERATOR
に設定する必要があります。
@Entity
@Table(name="EJB_ADDRESS")
public class Address implements Serializable {
...
@TableGenerator(
name="ADDRESS_TABLE_GENERATOR",
tableName="ADDRESS_GENERATOR_TABLE",
pkColumnValue="ADDRESS_SEQ"
)
@Id @GeneratedValue(strategy="TABLE", generator="ADDRESS_TABLE_GENERATOR")
@Column(name="ADDRESS_ID")
public Integer getId() {
return id;
}
...
}
例7-7に、@SequenceGenerator
アノテーションを使用して、データベースにより提供される順序オブジェクトに基づいて
主キー値ジェネレータを指定する方法を示します。TopLink JPA永続性プロバイダは、
デプロイ時にこのオブジェクトの作成を試行します。JPA永続性プロバイダで作成できない場合は、
データベース・ドキュメントに従って、デプロイ前にこの順序オブジェクトが存在していることを確認する必要があります。
Address
の新規インスタンスが作成されると、エンティティ・フィールドid
の
新しい値がデータベース順序オブジェクトADDRESS_SEQ
から取得されます。
この場合は、@GeneratedValue
アノテーションの属性strategy
をSEQUENCE
に設定し、
generator
をADDRESS_SEQUENCE_GENERATOR
に設定する必要があります。
@Entity
@Table(name="EJB_ADDRESS")
public class Address implements Serializable {
...
@SequenceGenerator(
name="ADDRESS_SEQUENCE_GENERATOR",
sequenceName="ADDRESS_SEQ"
)
@Id @GeneratedValue(strategy="SEQUENCE", generator="ADDRESS_SEQUENCE_GENERATOR")
@Column(name="ADDRESS_ID")
public Integer getId() {
return id;
}
...
}
例7-8に、@GeneratedValue
アノテーションを使用して主キーID列(自動番号列)に基づいて
主キー値ジェネレータを指定する方法を示します。Address
の新規インスタンスが保存されている場合は、データベースによって値がID列に割り当てられます。
この場合、TopLink JPA永続性プロバイダによって、挿入済の行が再び読み取られ、id
がこの値に設定されるようメモリー内のAddress
エンティティが更新されます。
@Entity
@Table(name="EJB_ADDRESS")
public class Address implements Serializable {
...
@Id @GeneratedValue(strategy="IDENTITY")
public Integer getId() {
return id;
}
...
}
次のように、TopLinkエンティティ・マネージャがエンティティを維持するデータベース表の特性を定義できます。
これは、既存のデータベース・スキーマがある場合に特に重要です。
既存のデータベース・スキーマがない場合は、この構成を省略して、表および列の定義をOC4Jに委任できます。デプロイ時に、OC4Jはクラス名およびデータ・メンバー名に基づいてデフォルトの表名および列名を作成します。
プライマリ表は、TopLinkエンティティ・マネージャがエンティティを維持する表です。特に、エンティティの主キーを格納する表です(「JPAエンティティの主キーの構成」を参照)。オプションで、エンティティの永続データが複数の表に格納されている場合は、1つ以上のセカンダリ表(「セカンダリ表の構成」を参照)も指定できます。
プライマリ表はエンティティ・クラス・レベルで定義します。
例7-9に、@Table
アノテーションを使用してEmployee
クラスのプライマリ表を定義する方法を示します。TopLinkエンティティ・マネージャは、このエンティティのインスタンスをEJB_EMPLOYEE
という名前の表に維持します。
@Entity
@Table(name="EJB_EMPLOYEE")
public class Employee implements Serializable {
...
}
1つ以上のセカンダリ表を指定して、エンティティの永続データが複数の表に格納されていることを示します。セカンダリ表を指定する前に、まずプライマリ表(「プライマリ表の構成」を参照)を指定する必要があります。
セカンダリ表はエンティティ・クラス・レベルで定義します。
1つ以上のセカンダリ表を指定する場合は、その表に格納される永続フィールドの列定義
(「列の構成」を参照)にセカンダリ表名を指定できます。これにより、エンティティ永続フィールドを複数の表に分散できます。
例7-10に、@SecondaryTable
アノテーションを使用して、エンティティの永続データの一部がEJB_SALARY
という名前の表に格納されることを指定する方法を示します。
@Entity
@Table(name="EJB_EMPLOYEE")
@SecondaryTable(name="EJB_SALARY")
public class Employee implements Serializable {
...
}
デフォルトでは、列はTopLinkエンティティ・マネージャがフィールドの値を格納するプライマリ表(「プライマリ表の構成」を参照)の列の名前です。
プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで列を定義します。
1つ以上のセカンダリ表を指定した場合(「セカンダリ表の構成」を参照)は、列定義にセカンダリ表名を指定できます。これにより、エンティティ永続フィールドを複数の表に分散できます。
例7-11に、@Column
アノテーションを使用してフィールドfirstName
のプライマリ表の列F_NAME
を指定する方法を示します。
@Column(name="F_NAME")
public String getFirstName() {
return firstName;
}
例7-12に、@Column
アノテーションを使用してフィールドsalary
のセカンダリ表EMP_SALARY
の列SALARY
を指定する方法を示します。
@Column(name="SALARY", secondaryTable="EMP_SALARY")
public String getSalary() {
return salary;
}
結合列では、エンティティ・アソシエーションまたはセカンダリ表を結合するためのマッピングされた外部キー列を指定します。
結合列は、次のもので定義できます。
例7-13に、@JoinColumn
アノテーションを使用してセカンダリ表で結合列を指定する方法を示します。詳細は、「セカンダリ表の構成」を参照してください。
@Entity
@Table(name="EJB_EMPLOYEE")
@SecondaryTable(name="EJB_SALARY")
@JoinColumn(name="EMP_ID", referencedColumnName="EMP_ID")
public class Employee implements Serializable {
...
}
例7-14に、@JoinColumn
アノテーションを使用して1対1マッピングで結合列を指定する方法を示します。詳細は、「1対1マッピングの構成」を参照してください。
@OneToOne(cascade=ALL, fetch=LAZY)
@JoinColumn(name="ADDR_ID")
public Address getAddress() {
return address;
}
例7-15に、@JoinColumn
アノテーションを使用して多対1マッピングで結合列を指定する方法を示します。詳細は、「多対1マッピングの構成」を参照してください。
@ManyToOne(cascade=PERSIST, fetch=LAZY)
@JoinColumn(name="MANAGER_ID", referencedColumnName="EMP_ID")
public Employee getManager() {
return manager;
}
例7-16に、@JoinColumn
アノテーションを使用して1対多マッピングで結合列を指定する方法を示します。詳細は、「1対多マッピングの構成」を参照してください。
@OneToMany(cascade=PERSIST)
@JoinColumn(name="MANAGER_ID", referencedColumnName="EMP_ID")
public Collection getManagedEmployees() {
return managedEmployees;
}
JPAエンティティでは、次のようにコンテナ管理の関連性(CMR)フィールド(「JPAエンティティのコンテナ管理の関連性フィールドとは」を参照)を定義します。
基本マッピングを使用して、プリミティブまたはJDKオブジェクト値を含むフィールドをマッピングします。たとえば、基本マッピングを使用して、String
属性をVARCHAR
列に格納します。
プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで基本マッピングを定義します。
オプションで、データベースからデータをフェッチする方針を定義できます(「遅延ロードの構成」を参照)。
詳細は、『Oracle TopLink開発者ガイド』のフィールドへの直接マッピングの理解に関する項を参照してください。
例7-17に、@Basic
アノテーションを使用してフィールドfirstName
の基本マッピングを指定する方法を示します。
@Basic()
@Column(name="F_NAME")
public String getFirstName() {
return firstName;
}
ラージ・オブジェクト(LOB)マッピングを使用して、永続プロパティまたはフィールドをデータベースでサポートされているLOBタイプにLOBとして維持することを指定します。LOBには、バイナリ(BLOB)型または文字(CLOB)型があります。
プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルでラージ・オブジェクト・マッピングを定義します。
詳細は、次を参照してください。
例7-18に、@Lob
アノテーションを使用してフィールドimage
のラージ・オブジェクト・マッピングを指定する方法を示します。
@Lob(fetch=EAGER, type=BLOB)
@Column(name="IMAGE")
public Byte[] getImage() {
return image;
}
シリアライズ・オブジェクト・マッピングを使用して、永続プロパティをバイトのシリアライズ・ストリームに維持することを指定します。
プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルでシリアライズ・オブジェクトを定義します。
詳細は、次を参照してください。
例7-19に、@Serialized
アノテーションを使用してフィールドpicture
のシリアライズ・オブジェクト・マッピングを指定する方法を示します。
@Serialized(fetch=EAGER)
@Column(name="PICTURE")
public Byte[] getPicture() {
return picture;
}
1対1マッピングを使用して、2つのJavaオブジェクト間の単純なポインタ参照を表します。Javaでは、属性に格納されている単一のポインタが、ソース・オブジェクトとターゲット・オブジェクト間のマッピングを表します。リレーショナル・データベース表は、外部キーを使用してこれらのマッピングを実装します。
プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで1対1マッピングを定義します。
詳細は、『Oracle TopLink開発者ガイド』の1対1マッピングの理解に関する項を参照してください。
例7-20に、@OneToOne
アノテーションを使用してフィールドaddress
の1対1マッピングを指定する方法を示します。
@OneToOne(cascade=ALL, fetch=LAZY)
@JoinColumn(name="ADDR_ID")
public Address getAddress() {
return address;
}
多対1マッピングを使用して、2つのJavaオブジェクト間の単純なポインタ参照を表します。Javaでは、属性に格納されている単一のポインタが、ソース・オブジェクトとターゲット・オブジェクト間のマッピングを表します。リレーショナル・データベース表は、外部キーを使用してこれらのマッピングを実装します。
プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで多対1マッピングを定義します。
詳細は、『Oracle TopLink開発者ガイド』の多対1マッピングの理解に関する項を参照してください。
例7-21に、@ManyToOne
アノテーションを使用してフィールドmanager
の多対1マッピングを指定する方法を示します。
@ManyToOne(cascade=PERSIST, fetch=LAZY)
@JoinColumn(name="MANAGER_ID", referencedColumnName="EMP_ID")
public Employee getManager() {
return manager;
}
1対多マッピングを使用して、単一のソース・オブジェクトとターゲット・オブジェクトのコレクションの間の関連を表します。この関連は、Javaではターゲット・オブジェクトのVector
(またはその他のコレクション・タイプ)を使用して簡単に実装でき、リレーショナル・データベースを使用すると実装するのが難しいものの例です。
プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで1対多マッピングを定義します。
詳細は、『Oracle TopLink開発者ガイド』の1対多マッピングの理解に関する項を参照してください。
例7-22に、@OneToMany
アノテーションを使用してフィールドmanagedEmployees
の1対多マッピングを指定する方法を示します。
@OneToMany(cascade=PERSIST)
@JoinColumn(name="MANAGER_ID", referencedColumnName="EMP_ID")
public Collection getManagedEmployees() {
return managedEmployees;
}
多対多マッピングを使用して、ソース・オブジェクトのコレクションとターゲット・オブジェクトのコレクションの間の関連を表します。このマッピングには、ソース・レコードとターゲット・レコードの間の関連付けを管理するための中間表(関連表)の作成が必要です。
プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで多対多マッピングを定義します。
詳細は、『Oracle TopLink開発者ガイド』の多対多マッピングの理解に関する項を参照してください。
例7-23に、@ManyToMany
アノテーションを使用してフィールドprojects
の多対多マッピングを指定する方法、および@JoinTable
アノテーションを使用して関連表を指定する方法を示します。
@ManyToMany(cascade=PERSIST)
@JoinTable(
name="EJB_PROJ_EMP",
joinColumns=@JoinColumn(name="EMP_ID", referencedColumnName="EMP_ID"),
inverseJoinColumns=@JoinColumn(name="PROJ_ID", referencedColumnName="PROJ_ID")
)
public Collection getProjects() {
return projects;
}
所有(親またはソース)エンティティおよび被所有(子またはターゲット)エンティティという2つのエンティティの間に厳密な1対1関連があり、被所有エンティティのすべての属性を所有エンティティと同じ表から取得できる場合、これらのエンティティは集約により関連しています。したがって、所有エンティティが存在する場合、被所有エンティティも存在する必要があり、所有エンティティが破棄された場合は、被所有エンティティも破棄されます。
集約マッピングでは、被所有エンティティのデータ・メンバーを所有エンティティの基礎となるデータベース表のフィールドに関連付けることができます。
所有エンティティでは、被所有フィールドまたはsetterを埋込みとして指定します。
被所有エンティティでは、クラスを埋込み可能として指定し、それを所有エンティティの表名に関連付けます。
所有エンティティでは、被所有エンティティで行われた列指定(「列の構成」を参照)をオーバーライドできます。
詳細は、『Oracle TopLink開発者ガイド』の集約マッピングの理解に関する項を参照してください。
例7-24に、@Embedded
アノテーションを使用してフィールドperiod
の集約マッピングを指定する方法を示します。このフィールドには、EmploymentPeriod
のインスタンスが含まれています。例7-25に、@Embeddable
アノテーションを使用してEmploymentPeriod
エンティティ・クラスを集約マッピングで使用可能として指定する方法、および@Table
アノテーション(「プライマリ表の構成」を参照)を使用してこのクラスを所有エンティティの表に関連付ける方法を示します。
@Entity
@Table(name="EJB_EMPLOYEE")
public class Employee implements Serializable {
...
@Embedded
public EmploymentPeriod getPeriod() {
return period;
}
...
}
例7-25 @Embeddable
@Embeddable
@Table(name="EJB_EMPLOYEE")
public class EmploymentPeriod implements Serializable {
private Date startDate;
private Date endDate;
...
}
所有エンティティで@AttributeOverride
を使用して(例7-26を参照)、被所有エンティティで行われた列定義をオーバーライドできます(例7-27を参照)。
@Entity
@Table(name="EJB_EMPLOYEE")
public class Employee implements Serializable {
...
@Embedded({
@AttributeOverride(name="startDate", column=@Column("EMP_START")),
@AttributeOverride(name="endDate", column=@Column("EMP_END"))}
)
public EmploymentPeriod getPeriod() {
return period;
}
...
}
例7-27 @Embeddableおよび@Column
@Embeddable
@Table(name="EJB_EMPLOYEE")
public class EmploymentPeriod implements Serializable {
@Column("START_DATE")
private Date startDate;
@Column("END_DATE")
private Date endDate;
...
}
TopLinkオプティミスティック・バージョン・ロック・ポリシーで使用するためにエンティティ・フィールドをバージョン・フィールドとして機能させることを指定できます。OC4Jは、再アタッチ時に整合性を保証するため(「エンティティBeanインスタンスの連結解除およびマージ」を参照)、また全体的なオプティミスティック同時性制御のためにこのバージョン・フィールドを使用します。
オプティミスティック・ロック・バージョン・フィールドは、プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで定義します。
詳細は、『Oracle TopLink開発者ガイド』のオプティミスティック・バージョン・ロック・ポリシーに関する項を参照してください。
例7-28に、@Version
アノテーションを使用して、列VERSION
を使用したオプティミスティック・バージョン・ロック・ポリシーを定義する方法を示します。
@Version
@Column(name="VERSION")
public int getVersion() {
return version;
}
EJB 3.0のすべてのマッピング・タイプ(基本および関連マッピング)で、次のいずれかを使用してデータベースからデータをフェッチする方針を定義できます。
FetchType.LAZY
: エンティティが取得されるときに、永続フィールドの値は取得されません。値が取得されるのは、フィールドへのアクセスが発生した時点です。
FetchTyep.EAGER
: エンティティが取得されるときに、永続フィールドの値も取得されます。
デフォルトでは、すべての永続フィールドが即座にフェッチされます。
EJB 3.0アプリケーションでfinderを使用する場合、finderレベルで遅延ロードを構成できます。これは、EJB 2.1のorion-ejb-jar.xml
ファイルを使用して構成するOracle固有のオプションです。詳細は、「finderメソッドにおける遅延ロードの構成」を参照してください。
例7-29に、@Basic
アノテーションを使用してLAZY
のフェッチ方針を定義する方法を示します。
@Basic(fetch=FetchType.LAZY)
@Column(name="F_NAME")
public String getFirstName() {
return firstName;
}
JPAエンティティ・クラス・メソッドを次のライフ・サイクル・イベントのコールバック・メソッドとして指定できます。
エンティティ・クラス・メソッドは、次のシグネチャを持つ必要があります。
int <METHOD>()
エンティティ・クラス・メソッドには、ejb
で始まらないかぎり自由にメソッド名を割り当てることができます。
詳細は、次を参照してください。
次のいずれかのアノテーションを使用して、JPAエンティティ・クラス・メソッドをライフ・サイクル・コールバック・メソッドとして指定できます。
例7-30に、@PrePersist
アノテーションを使用して、JPAエンティティ・クラス・メソッドinitialize
をライフ・サイクル・コールバック・メソッドとして指定する方法を示します。
@Entity
@Table(name="EJB_PROJECT")
public class Project implements Serializable {
...
@Id()
@Column(name="PROJECT_ID", primaryKey=true)
public Integer getId() {
return id;
}
...
@PrePersist
public int initialize() {
...
}
}
JPAエンティティのエンティティ・リスナー・クラスのエンティティ・リスナー・メソッドをライフ・サイクル・コールバック・メソッドとして指定できます。
エンティティ・リスナー・クラスでライフ・サイクル・コールバック・リスナー・メソッドを構成するには、次のようにします。
これは、任意のPOJOクラスにすることができます。
JPAエンティティ・リスナー・クラスに定義するコールバック・メソッドには、次のシグネチャを割り当てます。
void <METHOD>(Object)
Object
の引数型、またはエンティティ・リスナー・クラスを関連付けるJPAエンティティ・クラスの型を指定できます。
ライフ・サイクル・イベントは1つのコールバック・リスナー・メソッドにのみ関連付けることができますが、特定のコールバック・リスナー・メソッドは1つ以上のライフ・サイクル・イベントに関連付けることができます。
詳細は、次を参照してください。
詳細は、次を参照してください。
詳細は、次を参照してください。
次のいずれかのアノテーションを使用して、JPAエンティティ・リスナー・メソッドをライフ・サイクル・コールバック・メソッドとして指定できます。
例7-31に、@PostConstruct
および@PreDestroy
アノテーションを使用して、JPAエンティティ・リスナー・メソッドmyPostConstruct
およびmyPreDestroy
をそれぞれライフ・サイクル・コールバック・メソッドとして指定する方法を示します。
public class MyProjectEntityListener {
...
@PostConstruct
public void myPostConstruct (Project obj) { // or just Object
...
}
@PreDestroy
public void myPreDestroy (Project obj) { // or just Object
...
}
}
エンティティ・リスナー・クラスは、@EntityListeners
アノテーションを使用してJPAエンティティに関連付けることができます。
例7-32に、例7-31のエンティティ・リスナー・クラスをJPAエンティティ・クラスに関連付ける方法を示します。
@PrePersist
のライフ・サイクル・メソッドは、JPAエンティティ・クラスそれ自体のメソッドです(「JPAエンティティのライフ・サイクル・コールバック・メソッドの構成」を参照)。
@Entity
@EntityListeners(MyProjectEntityListener.class)
@Table(name="EJB_PROJECT")
public class Project implements Serializable {
...
@Id
@Column(name="PROJECT_ID", primaryKey=true)
public Integer getId() {
return id;
}
...
@PrePersist
public int initialize() {
...
}
}
OC4Jでは、クラスまたはクラス階層をリレーショナル・データベース・スキーマにマッピングするために次の継承計画がサポートされます。
アノテーションを使用して、これらのアプローチを構成できます(「アノテーションの使用方法」を参照)。
この計画では、サブクラスに固有のフィールドが、親クラスに共通のフィールドとは異なる表にマッピングされ、サブクラスをインスタンス化するために結合が実行されます。
クラス階層のルートは、単一表で表されます。各サブクラスは、(スーパークラスから継承されていない)サブクラスに固有の列およびサブクラスの主キーを表す列を含む別の表で表されます。スーパークラスに対する追加の状態がサブクラスにない場合は、別の表は不要です。
サブクラス表に主キー列がある場合、その主キー列はスーパークラス表の主キーに対する外部キーとして機能します。サブクラス表の主キー列の名前がスーパークラス表の主キー列の名前と同じ場合、OC4Jはこの関連を推測します。サブクラス表の主キー列名がスーパークラス表の主キー列の名前と同じでない場合(または、サブクラス表に主キー列がない場合)は、エンティティ・サブクラスのプライマリ表をスーパークラスのプライマリ表に結合するために使用するサブクラス表の列を指定する必要があります。
スーパークラスのプライマリ表には、識別子列として機能する列もあります。つまり、行で表されるインスタンスが属する特定のサブクラスを識別する値を持つ列です。
詳細は、「アノテーションによる結合サブクラスの継承の構成」を参照してください。
この計画では、階層内のすべてのクラスが単一表にマッピングされます。表には、識別子列として機能する列があります。追加の状態を追加する各サブクラスは、この単一表でのみこの新しい状態にマッピングされます。このような列は、そのサブクラスでのみ使用されます。
詳細は、「アノテーションによる単一表の継承の構成」を参照してください。
この項の内容は次のとおりです。
次の例では、結合サブクラスのアプローチ(「結合されたサブクラス」を参照)を使用して継承を構成する方法を示します。例7-33では、@Inheritance
アノテーションをベース・クラスProject
で使用する方法を示します。例7-34および例7-35では、@Inheritance
アノテーションをそれぞれ派生クラスLargeProject
およびSmallProject
で使用する方法を示します。
プライマリ表は、Project
とSmallProject
の両方がマッピングされるEJB_PROJECT
です。EJB_PROJECT
には、値がそれぞれP
、L
およびS
であるProject
、LargeProject
およびSmallProject
を表すPROJ_TYPE
という識別子列があります。LargeProject
は、状態をProject
に追加するため、固有の表EJB_LPROJECT
にマッピングされます。この表には、LargeProject
に固有のBUDGET
などのフィールドが含まれています。EJB_LPROJECT
には、主キー列がありません。かわりに、EJB_PROJECT
の主キーと同じ名前を持つ外部キー(PROJ_ID
)があります。
例7-34では、LargeProject
クラスの主キー列名(LARGE_PROJECT_ID
)はスーパークラス表(ID
)の主キー列の名前と同じでないため、@InheritanceJoinColumn
アノテーションを使用して、LargeProject
プライマリ表をそのスーパークラスのプライマリ表に結合するために使用する列を指定する必要があります。
@Entity
@Table(name="EJB_PROJECT")
@Inheritance(strategy=JOINED, discriminatorValue="P")
@DiscriminatorColumn(name="PROJ_TYPE")
public class Project implements Serializable {
...
@Id()
@Column(name="PROJECT_ID", primaryKey=true)
public Integer getId() {
return id;
}
...
}
例7-34 @Inheritance: 結合サブクラス継承の派生クラスLargeProject
@Entity
@Table(name="EJB_LPROJECT")
@Inheritance(discriminatorValue="L")
@InheritanceJoinColumn(name="LARGE_PROJECT_ID")
public class LargeProject extends Project {
...
@Id()
@Column(name="LARGE_PROJECT_ID", primaryKey=true)
public Integer getProjectId() {
return projectId;
}
...
}
例7-35 @Inheritance: 結合サブクラス継承の派生クラスSmallProject
@Entity
@Table(name="EJB_PROJECT")
@Inheritance(discriminatorValue="S")
public class SmallProject extends Project {
...
}
次の例では、各クラス階層の単一表のアプローチ(「各クラス階層の単一表」を参照)を使用して継承を構成する方法を示します。例7-33では、@Inheritance
アノテーションをベース・クラスProject
で使用する方法を示します。例7-34および例7-35では、@Inheritance
アノテーションがそれぞれ派生クラスLargeProject
およびSmallProject
でどのように不要であるかを示します。
プライマリ表は、Project
とSmallProject
の両方がマッピングされるEJB_PROJECT
です。EJB_PROJECT
表には、Project
のすべての列およびLargeProject
でのみ使用される追加列(BUDGET
)が含まれます。
@Entity
@Table(name="EJB_PROJECT")
@Inheritance(strategy=SINGLE_TABLE, discriminatorValue="P")
@DiscriminatorColumn(name="PROJ_TYPE")
public class Project implements Serializable {
...
}
例7-37 @Inheritance: 単一表継承の派生クラスLargeProject
@Entity
@Inheritance(discriminatorValue="L")
public class LargeProject extends Project {
...
}
例7-38 @Inheritance: 単一表継承の派生クラスSmallProject
@Entity
@Inheritance(discriminatorValue="S")
public class SmallProject extends Project {
...
}
|
Copyright © 2002, 2008 Oracle Corporation. All Rights Reserved. |
|