@OneToOneアノテーション
UserとUserAttributeが1対1の関係を作成します。
@Entity public class User { private Long id; private String name; private UserAttribute attribute; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY) public UserAttribute getAttribute() { return attribute; } public void setAttribute(UserAttribute attribute) { this.attribute = attribute; } }
@Entity @Table(name="USER_ATTR") public class UserAttribute { private Long id; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
とすることで以下のようなテーブルが作成されます。
USER
ID | NAME | ATTRIBUTE_ID |
1 | Thome | 1 |
USER_ATTR
ID |
1 |
テーブルへの永続化は、以下の様にUserの保存のみで2つのテーブルへ行われます。
User u = new User(); UserAttribute ua = new UserAttribute(); u.setName("Thome"); u.setAttribute(ua); getHibernateTemplate.save(u);
上記では、「fetch=FetchType.LAZY」としているため、Userを取得時には以下の様なSQLが発行されます。
select user0_.id as id1_0_, user0_.attribute_id as attribute3_1_0_, user0_.name as name1_0_ from User user0_ where user0_.id=1L
UserクラスのgetAttribute()を呼び出した時点で、USER_ATTRテーブルへのSQLが発行されます。
「fetch=FetchType.EAGER」とすると以下のようなSQLが発行され、2つのクラスが同時に得られます。
select user0_.id as id1_1_, user0_.attribute_id as attribute3_1_1_, user0_.name as name1_1_, userattrib1_.id as id2_0_ from User user0_ left outer join USER_ATTR userattrib1_ on user0_.attribute_id=userattrib1_.id where user0_.id=1L
@OneToManyと@ManyToOneアノテーション
Order(注文)とOrderLine(注文明細)の1対多関係のリレーションはをアノテーションで指定します。それぞれのクラス間はお互いに参照を持つ双方向関連のクラス定義としています。注文テーブルは以下の様に@OneToManyを指定する。mappedByには双方向関連の参照される側のプロパティ名を指定します。
@Entity @Table(name="ORDER_TBL") public class Order implements Serializable { private Long id; private Set<OrderLine> orderDetails = new HashSet<OrderLine>(); @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long getId() { return id; } @OneToMany(mappedBy="order") public Set<OrderLine> getOrderLines() { return orderLines; } // ・・・ }
注文明細側は、@ManyToOne を指定。
@javax.persistence.Entity public class OrderLine implements Serializable { private Long id; private Order order; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long getId() { return id; } @ManyToOne public Order getOrder() { return order; } // ・・・ }
これにより1対多関連がマッピングされます。
@OneToManyにfetchとして以下のように指定するとイガーフェッチとなります。Orderをデータベースから取得した場合、関連するOrderLineを同時に取得します。
@Entity @Table(name="ORDER_TBL") public class Order implements Serializable { // ・・・ @OneToMany(mappedBy="orderContent", fetch=FetchType.EAGER) public Set<OrderLine> getOrderLines() { return orderLines; }
Callback系アノテーション
Entityの永続化操作のタイミングで任意の操作を行うためにコールバック用のアノテーションが用意されています。
@PrePersist | オブジェクトの永続化前に実行する処理を指定 |
@PostPersist | オブジェクトの永続化後に実行する処理を指定 |
@PreUpdate | オブジェクトの属性が更新前に実行する処理を指定 |
@PostUpdate | オブジェクトの属性が更新後に実行する処理を指定 |
@PreRemove | オブジェクトの削除前に実行する処理を指定 |
@PostRemove | オブジェクトの削除後に実行する処理を指定 |
@PostLoad | オブジェクトのデータがデータベースから読み込まれる前に実行する処理を指定 |
Entityクラスのメソッドに上記アノテーションを指定することで、任意の操作が実現できます。典型的な例では、更新時に更新日時と更新者IDを埋め込むような場合に重宝するでしょう。
@PreUpdate private void preUpdate() { setUpdateDate(new Date()); setUpdateUser(getUserId()); }
Customerの年齢を永続化のタイミングで更新したい場合など、
@Entity public class Customer { // ・・・ @PostLoad @PostPersist @PostUpdate public void calculateAge() { // 年齢計算して設定 }
@Where
Hibernate独自のアノテーション。クラスに付与することで、エンティティへのアクセス時の条件を指定できます。
@Entity @Where(clause="delflg <> 1") public class Customer {
クラスに付けると、そのEntityのアクセスのwhere句としして、"delflg <> 1"の条件を付与してくれます。
Pro JPA 2 (Expert's Voice in Java)
- 作者: Mike Keith,Merrick Schincariol
- 出版社/メーカー: Apress
- 発売日: 2013/09/26
- メディア: ペーパーバック
- この商品を含むブログを見る