データ更新管理

使用可能

5.1 データ変更時刻

さまざまなレコードをデータベースに長年保存すると、次の 2 つの疑問が生じることがよくあります。

  • このエントリがデータベースに追加されたのはいつですか?
  • このエントリが最後に変更されたのはいつですか?

これらは頻繁に行われるタスクであるため、データベース内のほぼすべてのテーブルに 2 つの列が追加されます。

  • 作成時間
  • updated_time

1 つ目はレコードの作成日時を保存し、2 つ目は最後に変更された日時を保存します。そして、各 Entity クラスにはフィールドがあります。

@Entity
@Table(name = "entities")
public class Entity {
  ...

  @Column(name="created_time")
  private Date created;

  @Column(name="updated_time")
  private Date updated;
}

@CreationTimestampHibernate は、データベース内のオブジェクトが 2 つの注釈とを使用して更新されるタイミングを制御するすべての作業を実行できます@UpdateTimestamp

例:

@Entity
@Table(name = "entities")
public class Entity {
  ...

	@CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "create_date")
    private Date createDate;

	@UpdateTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "modify_date")
	private Date modifyDate;
}

これらの注釈が付けられた列には、オブジェクトが作成されたときと最後に変更されたときの正確な時間が常に保存されます。

5.2 @PrePersist アノテーション

オブジェクトの時間を制御するために、より複雑なスクリプトが必要な場合、Hibernate にはこの場合用のアノテーションも用意されています。これらはクラスメソッドをマークすることができ、Hibernate はオブジェクトをデータベースに保存するときにこれらのメソッドを呼び出します。このような注釈は合計 7 つあります。

@PrePersist オブジェクトがデータベースに保存される前に呼び出されます。(SQL挿入)
@PostPersist オブジェクトがデータベースに保存された直後に呼び出されます。(SQL挿入)
@PreRemove データベース内のオブジェクトを削除する前に呼び出されます。
@PostRemove オブジェクトがデータベースから削除された後に呼び出されます。
@PreUpdate データベース内のオブジェクトを更新 (SQL UPDATE) する前に呼び出されます。
@PostUpdate データベース内のオブジェクトの更新 (SQL UPDATE) の後に呼び出されます。
@PostLoad オブジェクトがデータベースからロードされた後に呼び出されます。

オブジェクトを作成および更新する正しい時間をクラスに伝える例を書いてみましょう。

@Entity
@Table(name = "entities")
public class Entity {
  ...

  @Column(name="created_time")
  private Date created;

  @Column(name="updated_time")
  private Date updated;

  @PrePersist
  protected void onCreate() {
    created = new Date();
  }

  @PreUpdate
  protected void onUpdate() {
  updated = new Date();
  }
}

Hibernate が初めてオブジェクトを保存すると、 の注釈が付けられたメソッドが呼び出されます@PrePersist。データベース内の既存のオブジェクトを更新する場合、アノテーション のマークが付いているメソッドを呼び出します@PreUpdate

5.3 EntityListeners の追加

本当に必要な場合は、Hibernate が呼び出すメソッドを、それが呼び出すオブジェクトから分離できます。JPA 仕様では、Entity オブジェクトの処理時に特定の時点で呼び出されるリスナー クラスを宣言できます。

類似した Entity オブジェクトが多数ある場合は、それらの一部を基本クラスに移動し、その動作を制御するリスナーを追加できます。例:

@MappedSuperclass
public abstract class BaseEntity {

    private Timestamp createdOn;

    private Timestamp updatedOn;

}


@Entity
public class User extends BaseEntity {

     @Id
     private Long id;

     private String name;
}

次に、BaseEntity クラスに対して特別なリスナー クラスを作成できます。

public class TimeEntityListener {

    public void onPersist(Object entity) {
    	if (entity instanceof BaseEntity) {
        	BaseEntity baseEntity = (BaseEntity) entity;
        	baseEntity.createdOn = now();
    	}
    }

    public void onUpdate(Object entity) {
    	if (entity instanceof BaseEntity) {
        	BaseEntity baseEntity = (BaseEntity) entity;
        	baseEntity.updatedOn = now();
    	}
    }

    private Timestamp now() {
    	return Timestamp.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)   );
    }
}

また、いくつかのアノテーションを使用して User クラスとそのリスナーを接続できます。

@Entity
@EntityListeners(class= TimeEntityListener.class)
public class User extends BaseEntity {

     @Id
     private Long id;

     private String name;
}

コメント
  • 人気
  • 新規
  • 古い
コメントを残すには、サインインしている必要があります
このページにはまだコメントがありません