JPAアノテーション – Hibernateアノテーション
JPAのアノテーションは、Javaのオブジェクトをデータベースのテーブルや列などにマッピングするために使用されます。Hibernateは、JPA仕様の最も人気のある実装であり、いくつかの追加のアノテーションを提供しています。今日は、JPAのアノテーションとHibernateのアノテーションについて、短いコード例と共に見ていきましょう。
JPAのアノテーション – Hibernateのアノテーション
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
JavaオブジェクトをデータベーステーブルにマッピングするためのJPAアノテーション
重要なJPAアノテーションの一部を見てみましょう。これらのアノテーションは、javax.persistenceパッケージに存在しています。
-
- javax.persistence.Entity: このアノテーションは、クラスがエンティティであることを指定します。このアノテーションは、クラス、インターフェース、列挙型に適用することができます。
import javax.persistence.Entity;
@Entity
public class Employee implements Serializable {
}
@Table: このアノテーションは、このエンティティがマッピングされるデータベースのテーブルを指定します。以下の例では、データは「employee」テーブルに格納されます。@Tableアノテーションのname属性を使用してテーブル名を指定します。
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = “employee”)
public class Employee implements Serializable {
}
@Column: @Columnアノテーションを使用して、列のマッピングを指定します。このアノテーションのname属性は、テーブルの列名を指定するために使用されます。
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = “employee”)
public class Employee implements Serializable {
@Column(name = “employee_name”)
private String employeeName;
}
@Id: このアノテーションは、エンティティの主キーを指定します。
import javax.persistence.*;
@Entity
@Table(name = “employee”)
public class Employee implements Serializable {
@Id
@Column(name = “id”)
private int id;
}
@GeneratedValue: このアノテーションは、主キーの値の生成戦略を指定します。
import javax.persistence.*;
@Entity
@Table(name = “employee”)
public class Employee implements Serializable {
@Id
@Column(name = “id”)
@GeneratedValue(strategy=SEQUENCE, generator=”ID_SEQ”)
private int id;
}
@Version: このアノテーションを使用することで、バージョニングや同時実行制御を制御することができます。
import javax.persistence.*;
@Entity
@Table(name = “employee”)
public class Employee implements Serializable {
@Version
@Column(name = “version”)
private Date version;
}
@OrderBy: @OrderByアノテーションを使用してデータをソートすることができます。以下の例では、すべてのemployees_addressをidで昇順に並べ替えます。
@OrderBy(“id asc”)
private Set employee_address;
@Transient: エンティティのすべての非staticで非transientなプロパティは永続的と見なされますが、@Transientアノテーションで指定されていない限りです。
@Transient
Private int employeePhone;
@Lob: 大きなオブジェクトは@Lobを使用して宣言されます。
@Lob
public String getEmployeeAddress() {
return employeeAddress;
}
上記のアノテーションセットは、エンティティを定義するために最も一般的に使用されるJPAのアノテーションです。
テーブル間のマッピングのためのHibernateアノテーション
私たちは、異なるテーブルとエンティティの関連付けマッピングを指定するために使用される別の注釈セットを持っています。以下のシナリオを考えて、例を挙げます。
- Tables ‘employee’ and ‘employeeDetail’ have one-to-one association and they share the same primary key.
- Tables ‘communication’ and ‘communicationDetail’ are linked by a foreign key. It is also a one to one association.
- Tables ‘communication’ and ‘employee’ are linked using a foreign key in many-to-one association with communication being the owner.
- Tables ‘employee’ and ‘employeeStatus’ are linked through a foreign key in many-to-one association with employee being the owner.
@OneToOneのEmployeeとEmployeeDetailエンティティは、同じ主キーを共有しており、@OneToOneと@PrimaryKeyJoinColumnを使用して関連付けることができます。この場合、EmployeeDetailのidプロパティは@GeneratedValueで注釈付けされていません。Employeeのid値がEmployeeDetailのidとして使用されます。
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne(cascade = CascadeType.MERGE)
@PrimaryKeyJoinColumn
private EmployeeDetail employeeDetail;
}
@Entity
@Table(name = "employeeDetail")
public class EmployeeDetail implements Serializable {
@Id
@Column(name = "id")
private int id;
}
注意すべきポイント:
- @PrimaryKeyJoinColumn should be used for associated entities sharing the same primary key.
- @JoinColumn & @OneToOne should be mappedBy attribute when foreign key is held by one of the entities.
通信と通信の詳細は、外部キーを介してリンクされているため、@OneToOneと@JoinColumnの注釈が使用できます。以下のスニペットで、通信のために生成されたIDは、通信の詳細のテーブルの「communication_id」列にマップされます。同じことを行うために@MapsIdが使用されます。
@Entity
@Table(name = "communicationDetail")
public class CommunicationDetail implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne
@MapsId
@JoinColumn(name = "communicationId")
private Communication communication;
}
@Entity
@Table(name = "communication")
public class Communication implements Serializable {
@Id
@Column(name = "ID")
@GeneratedValue
private Integer id;
@OneToOne(mappedBy = "communication", cascade = CascadeType.ALL)
private CommunicationDetail communicationDetail;
}
多くの従業員が同じステータスを共有できるため、従業員と従業員ステータスの関係は多対一です。同じことには @ManyToOne アノテーションが使用できます。
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@ManyToOne
@JoinColumn(name = "statusId")
private EmployeeStatus status;
}
@OneToManyの従業員からコミュニケーションへは、1対多の関係があります。この関係のオーナーはコミュニケーションであり、従業員には双方向の関係を作るために「mappedBy」属性を使用します。
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@OneToMany(mappedBy = "employee", fetch = FetchType.EAGER)
@OrderBy("firstName asc")
private Set communications;
}
@PrimaryKeyJoinColumnは、同じプライマリキーを共有するエンティティを関連付けるために使用されるアノテーションです。
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne(cascade = CascadeType.MERGE)
@PrimaryKeyJoinColumn
private EmployeeDetail employeeDetail;
}
@Entityのアノテーションには、@JoinColumnアノテーションが使用されます。これは、1対1または多対1の関連があり、外部キーがエンティティのうちの1つによって保持される場合に使用されます。
@ManyToOne
@JoinColumn(name = "statusId")
private EmployeeStatus status;
@JoinTable: @JoinTableとmappedByは、連想テーブルを介して関連付けられたエンティティに使用する必要があります。
@MapsId: 共有キーを持つ2つのエンティティを、@MapsIdアノテーションを使用して永続化することができます。
@OneToOne
@MapsId
@JoinColumn(name = "communicationId")
private Communication communication;
継承マッピングのためのHibernateアノテーション
今度は、Hibernateにおける継承マッピングアノテーションを理解しましょう。Hibernateは、基本的な継承マッピング戦略を3つサポートしています。
- table per class hierarchy
- table per subclass
- table per concrete class
各タイプについて、例を考えます。
-
- クラス階層ごとのテーブル – クラス階層ごとのシングルテーブル戦略。
-
- @Entity
-
- @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
-
- @DiscriminatorColumn(name=”cartype”, discriminatorType=DiscriminatorType.STRING )
@DiscriminatorValue(“Car”)
public class Car { }
@Entity
@DiscriminatorValue(“BMW”)
public class BMW extends Car { }
クラス/サブクラスごとのテーブル – サブクラス結合戦略。
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Ship implements Serializable {}
@Entity
@PrimaryKeyJoinColumn
public class Titanic extends Ship {}
具象クラスごとのテーブル。
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Aeroplane implements Serializable {}
@DiscriminatorColumn: その名前からも分かるように、このカラムは識別子であり、このアノテーションはSINGLE_TABLEおよびJOINEDの継承マッピング戦略のための識別子カラムを指定します。
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name=”cartype”, discriminatorType=DiscriminatorType.STRING )
JPAとHibernateのアノテーションについては以上です。参考文献:JSR338、Hibernate APIドキュメント。