ヘッダーをスキップ

Oracle Containers for J2EE Enterprise JavaBeans開発者ガイド
10g(10.1.3.1.0)

B31852-03
目次
目次
索引
索引

戻る 次へ

7 Java永続性APIの使用方法

この章では、JPAエンティティを使用するために構成できる様々なオプションについて説明します。

表7-1に、これらのオプションをリストし、基本オプション(ほとんどのアプリケーションに適用可能)であるか拡張オプション(より特殊なアプリケーションに適用可能)であるかを示します。

詳細は、次を参照してください。

JPAエンティティの主キーの構成

すべてのJPAエンティティには主キーが必要です。

主キーは単一のプリミティブ型またはJDKオブジェクト型のエンティティ・フィールドとして指定できます(「JPAエンティティの単純な主キー・フィールドの構成」を参照)。

個別のコンポジット主キー・クラスを使用して、1つ以上のプリミティブ型またはJDKオブジェクト型から構成されるコンポジット主キーを指定できます(「JPAエンティティのコンポジット主キー・クラスの構成」を参照)。

主キー値を自分で割り当てるか、主キー値ジェネレータに主キー・フィールドを関連付けることができます(「JPAエンティティの自動主キー生成の構成」を参照)。

JPAエンティティの単純な主キー・フィールドの構成

最も単純な主キーは、単一のプリミティブ型またはJDKオブジェクト型のエンティティ・フィールドとして指定する主キーです(「アノテーションの使用方法」を参照)。


注意

JPAエンティティの主キー・フィールドのコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.html#idを参照してください。 


アノテーションの使用方法

例7-1に、@Idアノテーションを使用してエンティティ・フィールドを主キーとして指定する方法を示します。この例では、主キー値は表ジェネレータを使用して生成されています
「JPAエンティティの自動主キー生成の構成」を参照)。

例7-1    @Idを使用した主キー

@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;
}

 

JPAエンティティのコンポジット主キー・クラスの構成

コンポジット主キーは、通常、2つ以上のプリミティブ型またはJDKオブジェクト型から構成されます。一般的に、コンポジット主キーが割り当てられるのは、データベース・キーが複数の列から構成されるレガシー・データベースからマッピングを行う場合です。このようなコンポジット主キーは、個別のコンポジット主キー・クラスを使用して指定できます(「アノテーションの使用方法」を参照)。

コンポジット主キー・クラスには、次の特性があります。

コンポジット主キー・クラスは、エンティティ・クラスに所有される埋込みクラスとするか、エンティティ・クラスの複数のフィールドまたはプロパティにマップされるフィールドを持つ非埋込みクラスとすることが可能です。非埋込みクラスの場合、コンポジット主キー・クラスの主キー・フィールドまたはプロパティの名前とエンティティ・クラスの主キー・フィールドまたはプロパティの名前は一致する必要があり、それらの型も同じである必要があります。

アノテーションの使用方法

例7-2に、典型的な埋込み可能コンポジット主キー・クラスを示します。また、例7-3に、@EmbeddedIdアノテーションを使用してこの埋込みコンポジット主キー・クラスでJPAエンティティを構成する方法を示します。

例7-2    埋込み可能コンポジット主キー・クラス

@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アノテーションを付ける必要もあります。

例7-4    非埋込みコンポジット主キー・クラス

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エンティティの自動主キー生成の構成

通常は、主キー・フィールド(「JPAエンティティの単純な主キー・フィールドの構成」を参照)を主キー値ジェネレータに関連付けて、エンティティ・インスタンスが作成されたときに新しい一意の主キー値が自動的に割り当てられるようにします。

表7-2に、定義できる主キー値ジェネレータのタイプをリストします。

表7-2    JPAエンティティの主キー値ジェネレータ 
タイプ  説明  参照先 

生成されたID表 

エンティティに対して生成された主キー値をコンテナが格納するために使用するデータベース表。通常は、表ベースの主キー生成を使用する複数のエンティティ・タイプにより共有されます。各エンティティ・タイプは、通常は表内の独自の行を使用して、そのエンティティ・クラスの主キー値を生成します。主キー値は正の整数です。 

『Oracle TopLink開発者ガイド』の表の順序付けに関する項 

表ジェネレータ 

名前で参照できる主キー・ジェネレータであり、パッケージ、クラス、メソッドまたはフィールド・レベルで定義されます。定義するレベルは、目的の可視性およびジェネレータの共有に依存します。有効範囲決定規則または可視性規則は実際には強制されません。使用されるレベルでジェネレータを定義することをお薦めします。

このジェネレータは、データベース表に基づいています。 

『Oracle TopLink開発者ガイド』の表の順序付けに関する項 

シーケンス・ジェネレータ 

名前で参照できる主キー・ジェネレータであり、パッケージ、クラス、メソッドまたはフィールド・レベルで定義されます。定義するレベルは、目的の可視性およびジェネレータの共有に依存します。有効範囲決定規則または可視性規則は実際には強制されません。使用されるレベルでジェネレータを定義することをお薦めします。

このジェネレータは、データベース・サーバーが提供する順序オブジェクトに基づいています。 

『Oracle TopLink開発者ガイド』のOracleデータベース・プラットフォームでのネイティブ順序付けに関する項

『Oracle TopLink開発者ガイド』のOracleデータベース・プラットフォーム以外でのネイティブ順序付けに関する項 


注意

EJB 3.0自動主キー生成のコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.html#sequencingを参照してください。 


アノテーションの使用方法

例7-6に、@TableGeneratorアノテーションを使用してデータベース表に基づいて主キー値ジェネレータを指定する方法を示します。TopLink JPA永続性プロバイダは、デプロイ時にこの表の作成を試行します。JPA永続性プロバイダで作成できない場合は、データベース・ドキュメントに従って、デプロイ前にこの表が存在していることを確認する必要があります。Addressの新規インスタンスが作成されると、エンティティ・フィールドidの新しい値がADDRESS_GENERATOR_TABLEから取得されます。この場合は、@GeneratedValueアノテーションの属性strategyTABLEに設定し、generatorADDRESS_TABLE_GENERATORに設定する必要があります。

例7-6    GeneratedValueのstrategyの表: @TableGenerator

@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アノテーションの属性strategySEQUENCEに設定し、
generatorADDRESS_SEQUENCE_GENERATORに設定する必要があります。

例7-7    GeneratedValueのstrategyの順序: @SequenceGenerator

@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エンティティが更新されます。

例7-8    @GeneratedValueのstrategyのID

@Entity
@Table(name="EJB_ADDRESS")
public class Address implements Serializable {
...
    @Id @GeneratedValue(strategy="IDENTITY")
    public Integer getId() {
        return id;
    }
...
}

表および列情報の構成

次のように、TopLinkエンティティ・マネージャがエンティティを維持するデータベース表の特性を定義できます。

これは、既存のデータベース・スキーマがある場合に特に重要です。

既存のデータベース・スキーマがない場合は、この構成を省略して、表および列の定義をOC4Jに委任できます。デプロイ時に、OC4Jはクラス名およびデータ・メンバー名に基づいてデフォルトの表名および列名を作成します。


注意

JPAエンティティ表および列のコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.htmlからダウンロードできます。 


プライマリ表の構成

プライマリ表は、TopLinkエンティティ・マネージャがエンティティを維持する表です。特に、エンティティの主キーを格納する表です(「JPAエンティティの主キーの構成」を参照)。オプションで、エンティティの永続データが複数の表に格納されている場合は、1つ以上のセカンダリ表(「セカンダリ表の構成」を参照)も指定できます。

プライマリ表はエンティティ・クラス・レベルで定義します。

アノテーションの使用方法

例7-9に、@Tableアノテーションを使用してEmployeeクラスのプライマリ表を定義する方法を示します。TopLinkエンティティ・マネージャは、このエンティティのインスタンスをEJB_EMPLOYEEという名前の表に維持します。

例7-9    @Table

@Entity
@Table(name="EJB_EMPLOYEE")
public class Employee implements Serializable {
...
}

 

セカンダリ表の構成

1つ以上のセカンダリ表を指定して、エンティティの永続データが複数の表に格納されていることを示します。セカンダリ表を指定する前に、まずプライマリ表(「プライマリ表の構成」を参照)を指定する必要があります。

セカンダリ表はエンティティ・クラス・レベルで定義します。

1つ以上のセカンダリ表を指定する場合は、その表に格納される永続フィールドの列定義
「列の構成」を参照)にセカンダリ表名を指定できます。これにより、エンティティ永続フィールドを複数の表に分散できます。

アノテーションの使用方法

例7-10に、@SecondaryTableアノテーションを使用して、エンティティの永続データの一部がEJB_SALARYという名前の表に格納されることを指定する方法を示します。

例7-10    @SecondaryTable

@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を指定する方法を示します。

例7-11    プライマリ表の@Column

@Column(name="F_NAME")
public String getFirstName() {
    return firstName;
}

例7-12に、@Columnアノテーションを使用してフィールドsalaryのセカンダリ表
EMP_SALARYの列SALARYを指定する方法を示します。

例7-12    セカンダリ表の@Column

@Column(name="SALARY", secondaryTable="EMP_SALARY")
public String getSalary() {
    return salary;
}

 

結合列の構成

結合列では、エンティティ・アソシエーションまたはセカンダリ表を結合するためのマッピングされた外部キー列を指定します。

結合列は、次のもので定義できます。

アノテーションの使用方法

例7-13に、@JoinColumnアノテーションを使用してセカンダリ表で結合列を指定する方法を示します。詳細は、「セカンダリ表の構成」を参照してください。

例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マッピングの構成」を参照してください。

例7-14    1対1マッピングでの@JoinColumn

@OneToOne(cascade=ALL, fetch=LAZY)
@JoinColumn(name="ADDR_ID")
public Address getAddress() {
    return address;
}

例7-15に、@JoinColumnアノテーションを使用して多対1マッピングで結合列を指定する方法を示します。詳細は、「多対1マッピングの構成」を参照してください。

例7-15    多対1マッピングでの@JoinColumn

@ManyToOne(cascade=PERSIST, fetch=LAZY)
@JoinColumn(name="MANAGER_ID", referencedColumnName="EMP_ID")
public Employee getManager() {
    return manager;
}

例7-16に、@JoinColumnアノテーションを使用して1対多マッピングで結合列を指定する方法を示します。詳細は、「1対多マッピングの構成」を参照してください。

例7-16    1対多マッピングでの@JoinColumn

@OneToMany(cascade=PERSIST)
@JoinColumn(name="MANAGER_ID", referencedColumnName="EMP_ID")
public Collection getManagedEmployees() {
    return managedEmployees;
}

 

JPAエンティティのコンテナ管理の関連性フィールドの構成

JPAエンティティでは、次のようにコンテナ管理の関連性(CMR)フィールド(「JPAエンティティのコンテナ管理の関連性フィールドとは」を参照)を定義します。

基本マッピングの構成

基本マッピングを使用して、プリミティブまたはJDKオブジェクト値を含むフィールドをマッピングします。たとえば、基本マッピングを使用して、String属性をVARCHAR列に格納します。

プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで基本マッピングを定義します。

オプションで、データベースからデータをフェッチする方針を定義できます(「遅延ロードの構成」を参照)。

詳細は、『Oracle TopLink開発者ガイド』のフィールドへの直接マッピングの理解に関する項を参照してください。


注意

EJB 3.0基本マッピングのコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.html#basicを参照してください。 


アノテーションの使用方法

例7-17に、@Basicアノテーションを使用してフィールドfirstNameの基本マッピングを指定する方法を示します。

例7-17    @Basic

@Basic()
@Column(name="F_NAME")
public String getFirstName() {
    return firstName;
}

 

ラージ・オブジェクト・マッピングの構成

ラージ・オブジェクト(LOB)マッピングを使用して、永続プロパティまたはフィールドをデータベースでサポートされているLOBタイプにLOBとして維持することを指定します。LOBには、バイナリ(BLOB)型または文字(CLOB)型があります。

プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルでラージ・オブジェクト・マッピングを定義します。

詳細は、次を参照してください。

アノテーションの使用方法

例7-18に、@Lobアノテーションを使用してフィールドimageのラージ・オブジェクト・マッピングを指定する方法を示します。

例7-18    @Lob

@Lob(fetch=EAGER, type=BLOB)
@Column(name="IMAGE")
public Byte[] getImage() {
    return image;
}

 

シリアライズ・オブジェクト・マッピングの構成

シリアライズ・オブジェクト・マッピングを使用して、永続プロパティをバイトのシリアライズ・ストリームに維持することを指定します。

プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルでシリアライズ・オブジェクトを定義します。

詳細は、次を参照してください。

アノテーションの使用方法

例7-19に、@Serializedアノテーションを使用してフィールドpictureのシリアライズ・オブジェクト・マッピングを指定する方法を示します。

例7-19    @Serialized

@Serialized(fetch=EAGER)
@Column(name="PICTURE")
public Byte[] getPicture() {
    return picture;
}

 

1対1マッピングの構成

1対1マッピングを使用して、2つのJavaオブジェクト間の単純なポインタ参照を表します。Javaでは、属性に格納されている単一のポインタが、ソース・オブジェクトとターゲット・オブジェクト間のマッピングを表します。リレーショナル・データベース表は、外部キーを使用してこれらのマッピングを実装します。

プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで1対1マッピングを定義します。

詳細は、『Oracle TopLink開発者ガイド』の1対1マッピングの理解に関する項を参照してください。


注意

EJB 3.0基本マッピングのコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.html#onetooneを参照してください。 


アノテーションの使用方法

例7-20に、@OneToOneアノテーションを使用してフィールドaddressの1対1マッピングを指定する方法を示します。

例7-20    @OneToOne

@OneToOne(cascade=ALL, fetch=LAZY)
@JoinColumn(name="ADDR_ID")
public Address getAddress() {
    return address;
}

多対1マッピングの構成

多対1マッピングを使用して、2つのJavaオブジェクト間の単純なポインタ参照を表します。Javaでは、属性に格納されている単一のポインタが、ソース・オブジェクトとターゲット・オブジェクト間のマッピングを表します。リレーショナル・データベース表は、外部キーを使用してこれらのマッピングを実装します。

プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで多対1マッピングを定義します。

詳細は、『Oracle TopLink開発者ガイド』の多対1マッピングの理解に関する項を参照してください。


注意

EJB 3.0基本マッピングのコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.html#manytooneを参照してください。 


アノテーションの使用方法

例7-21に、@ManyToOneアノテーションを使用してフィールドmanagerの多対1マッピングを指定する方法を示します。

例7-21    @ManyToOne

@ManyToOne(cascade=PERSIST, fetch=LAZY)
@JoinColumn(name="MANAGER_ID", referencedColumnName="EMP_ID")
public Employee getManager() {
    return manager;
}

1対多マッピングの構成

1対多マッピングを使用して、単一のソース・オブジェクトとターゲット・オブジェクトのコレクションの間の関連を表します。この関連は、Javaではターゲット・オブジェクトのVector(またはその他のコレクション・タイプ)を使用して簡単に実装でき、リレーショナル・データベースを使用すると実装するのが難しいものの例です。

プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで1対多マッピングを定義します。

詳細は、『Oracle TopLink開発者ガイド』の1対多マッピングの理解に関する項を参照してください。


注意

EJB 3.0基本マッピングのコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.html#onetomanyを参照してください。 


アノテーションの使用方法

例7-22に、@OneToManyアノテーションを使用してフィールドmanagedEmployeesの1対多マッピングを指定する方法を示します。

例7-22    @OneToMany

@OneToMany(cascade=PERSIST)
@JoinColumn(name="MANAGER_ID", referencedColumnName="EMP_ID")
public Collection getManagedEmployees() {
    return managedEmployees;
}

 

多対多マッピングの構成

多対多マッピングを使用して、ソース・オブジェクトのコレクションとターゲット・オブジェクトのコレクションの間の関連を表します。このマッピングには、ソース・レコードとターゲット・レコードの間の関連付けを管理するための中間表(関連表)の作成が必要です。

プロパティの1つ(getterまたはsetterメソッド)またはエンティティのフィールド・レベルで多対多マッピングを定義します。

詳細は、『Oracle TopLink開発者ガイド』の多対多マッピングの理解に関する項を参照してください。


注意

EJB 3.0基本マッピングのコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.html#manytomanyを参照してください。 


アノテーションの使用方法

例7-23に、@ManyToManyアノテーションを使用してフィールドprojectsの多対多マッピングを指定する方法、および@JoinTableアノテーションを使用して関連表を指定する方法を示します。

例7-23    @ManyToMany

@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開発者ガイド』の集約マッピングの理解に関する項を参照してください。


注意

EJB 3.0基本マッピングのコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30mappingannotations/doc/
how-to-ejb30-mapping-annotations.html#embeddedを参照してください。 


アノテーションの使用方法

例7-24に、@Embeddedアノテーションを使用してフィールドperiodの集約マッピングを指定する方法を示します。このフィールドには、EmploymentPeriodのインスタンスが含まれています。例7-25に、@Embeddableアノテーションを使用してEmploymentPeriodエンティティ・クラスを集約マッピングで使用可能として指定する方法、および@Tableアノテーション(「プライマリ表の構成」を参照)を使用してこのクラスを所有エンティティの表に関連付ける方法を示します。

例7-24    @Embedded

@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を参照)。

例7-26    @Embeddedおよび@AttributeOverride

@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を使用したオプティミスティック・バージョン・ロック・ポリシーを定義する方法を示します。

例7-28    @Version

@Version
@Column(name="VERSION")
public int getVersion() {
    return version;
}

 

遅延ロードの構成

EJB 3.0のすべてのマッピング・タイプ(基本および関連マッピング)で、次のいずれかを使用してデータベースからデータをフェッチする方針を定義できます。

デフォルトでは、すべての永続フィールドが即座にフェッチされます。

EJB 3.0アプリケーションでfinderを使用する場合、finderレベルで遅延ロードを構成できます。これは、EJB 2.1のorion-ejb-jar.xmlファイルを使用して構成するOracle固有のオプションです。詳細は、「finderメソッドにおける遅延ロードの構成」を参照してください。

アノテーションの使用方法

例7-29に、@Basicアノテーションを使用してLAZYのフェッチ方針を定義する方法を示します。

例7-29    @Basicのfetch属性

@Basic(fetch=FetchType.LAZY)
@Column(name="F_NAME")
public String getFirstName() {
    return firstName;
}

 

JPAエンティティのライフ・サイクル・コールバック・メソッドの構成

JPAエンティティ・クラス・メソッドを次のライフ・サイクル・イベントのコールバック・メソッドとして指定できます。

エンティティ・クラス・メソッドは、次のシグネチャを持つ必要があります。

int <METHOD>()

エンティティ・クラス・メソッドには、ejbで始まらないかぎり自由にメソッド名を割り当てることができます。

詳細は、次を参照してください。

アノテーションの使用方法

次のいずれかのアノテーションを使用して、JPAエンティティ・クラス・メソッドをライフ・サイクル・コールバック・メソッドとして指定できます。

例7-30に、@PrePersistアノテーションを使用して、JPAエンティティ・クラス・メソッドinitializeをライフ・サイクル・コールバック・メソッドとして指定する方法を示します。

例7-30    @PrePersist

@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エンティティのエンティティ・リスナー・クラスのライフ・サイクル・コールバック・リスナー・メソッドの構成

JPAエンティティのエンティティ・リスナー・クラスのエンティティ・リスナー・メソッドをライフ・サイクル・コールバック・メソッドとして指定できます。

エンティティ・リスナー・クラスでライフ・サイクル・コールバック・リスナー・メソッドを構成するには、次のようにします。

  1. エンティティ・リスナー・クラスを作成します。

    これは、任意のPOJOクラスにすることができます。

  2. エンティティ・リスナー・クラスにライフ・サイクル・コールバック・リスナー・メソッドを実装します。

    JPAエンティティ・リスナー・クラスに定義するコールバック・メソッドには、次のシグネチャを割り当てます。

    void <METHOD>(Object)
    
    

    Objectの引数型、またはエンティティ・リスナー・クラスを関連付けるJPAエンティティ・クラスの型を指定できます。

  3. ライフ・サイクル・イベントをコールバック・リスナー・メソッドに関連付けます。

    ライフ・サイクル・イベントは1つのコールバック・リスナー・メソッドにのみ関連付けることができますが、特定のコールバック・リスナー・メソッドは1つ以上のライフ・サイクル・イベントに関連付けることができます。

    詳細は、次を参照してください。

  4. インターセプタ・クラスをJPAエンティティに関連付けます。

    詳細は、次を参照してください。

詳細は、次を参照してください。

アノテーションの使用方法

次のいずれかのアノテーションを使用して、JPAエンティティ・リスナー・メソッドをライフ・サイクル・コールバック・メソッドとして指定できます。

例7-31に、@PostConstructおよび@PreDestroyアノテーションを使用して、JPAエンティティ・リスナー・メソッドmyPostConstructおよびmyPreDestroyをそれぞれライフ・サイクル・コールバック・メソッドとして指定する方法を示します。

例7-31    @PrePersistライフ・サイクル・リスナー・コールバック・メソッド

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エンティティのライフ・サイクル・コールバック・メソッドの構成」を参照)。

例7-32    エンティティ・リスナー・クラスと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() {
        ...
    }
}

JPAエンティティの継承の構成

OC4Jでは、クラスまたはクラス階層をリレーショナル・データベース・スキーマにマッピングするために次の継承計画がサポートされます。

アノテーションを使用して、これらのアプローチを構成できます(「アノテーションの使用方法」を参照)。


注意

EJB 3.0継承のコード例は、http://www.oracle.com/technology/tech/java/oc4j/ejb3/
howtos-ejb3/howtoejb30inheritance/doc/
how-to-ejb30-inheritance.htmlを参照してください。 


結合されたサブクラス

この計画では、サブクラスに固有のフィールドが、親クラスに共通のフィールドとは異なる表にマッピングされ、サブクラスをインスタンス化するために結合が実行されます。

クラス階層のルートは、単一表で表されます。各サブクラスは、(スーパークラスから継承されていない)サブクラスに固有の列およびサブクラスの主キーを表す列を含む別の表で表されます。スーパークラスに対する追加の状態がサブクラスにない場合は、別の表は不要です。

サブクラス表に主キー列がある場合、その主キー列はスーパークラス表の主キーに対する外部キーとして機能します。サブクラス表の主キー列の名前がスーパークラス表の主キー列の名前と同じ場合、OC4Jはこの関連を推測します。サブクラス表の主キー列名がスーパークラス表の主キー列の名前と同じでない場合(または、サブクラス表に主キー列がない場合)は、エンティティ・サブクラスのプライマリ表をスーパークラスのプライマリ表に結合するために使用するサブクラス表の列を指定する必要があります。

スーパークラスのプライマリ表には、識別子列として機能する列もあります。つまり、行で表されるインスタンスが属する特定のサブクラスを識別する値を持つ列です。

詳細は、「アノテーションによる結合サブクラスの継承の構成」を参照してください。

各クラス階層の単一表

この計画では、階層内のすべてのクラスが単一表にマッピングされます。表には、識別子列として機能する列があります。追加の状態を追加する各サブクラスは、この単一表でのみこの新しい状態にマッピングされます。このような列は、そのサブクラスでのみ使用されます。

詳細は、「アノテーションによる単一表の継承の構成」を参照してください。

アノテーションの使用方法

この項の内容は次のとおりです。

アノテーションによる結合サブクラスの継承の構成

次の例では、結合サブクラスのアプローチ(「結合されたサブクラス」を参照)を使用して継承を構成する方法を示します。例7-33では、@Inheritanceアノテーションをベース・クラスProjectで使用する方法を示します。例7-34および例7-35では、@Inheritanceアノテーションをそれぞれ派生クラスLargeProjectおよびSmallProjectで使用する方法を示します。

プライマリ表は、ProjectSmallProjectの両方がマッピングされるEJB_PROJECTです。EJB_PROJECTには、値がそれぞれPLおよびSであるProjectLargeProjectおよびSmallProjectを表すPROJ_TYPEという識別子列があります。LargeProjectは、状態をProjectに追加するため、固有の表EJB_LPROJECTにマッピングされます。この表には、LargeProjectに固有のBUDGETなどのフィールドが含まれています。EJB_LPROJECTには、主キー列がありません。かわりに、EJB_PROJECTの主キーと同じ名前を持つ外部キー(PROJ_ID)があります。

例7-34では、LargeProjectクラスの主キー列名(LARGE_PROJECT_ID)はスーパークラス表(ID)の主キー列の名前と同じでないため、@InheritanceJoinColumnアノテーションを使用して、LargeProjectプライマリ表をそのスーパークラスのプライマリ表に結合するために使用する列を指定する必要があります。

例7-33    @Inheritance: 結合サブクラス継承のベース・クラスProject

@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でどのように不要であるかを示します。

プライマリ表は、ProjectSmallProjectの両方がマッピングされるEJB_PROJECTです。EJB_PROJECT表には、Projectのすべての列およびLargeProjectでのみ使用される追加列(BUDGET)が含まれます。

例7-36    @Inheritance: 単一表継承のベース・クラスProject

@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 {
...
}


戻る 次へ
Oracle
Copyright © 2002, 2008 Oracle Corporation.

All Rights Reserved.
目次
目次
索引
索引