1.使用する必要があるデータベース列のタイプ
最初の質問は:
データベースでどのデータ型を使用しますか(MySQLの場合、JVMとは異なるタイムゾーンの可能性があります)?データ型はタイムゾーンを認識しますか?
MySQLでは、TIMESTAMP
カラムタイプはJDBCドライバーのローカルタイムゾーンからデータベースのタイムゾーンにシフトしますが'2038-01-19 03:14:07.999999
、最大でまでのタイムスタンプしか保存できないため、将来的には最適ではありません。
そのため、DATETIME
この上限の制限がない代わりに使用することをお勧めします。ただし、DATETIME
タイムゾーンは認識されません。したがって、このため、データベース側でUTCを使用し、hibernate.jdbc.time_zone
Hibernateプロパティを使用するのが最善です。
hibernate.jdbc.time_zone
設定の詳細については、こちらの記事をご覧ください。
2.使用する必要があるエンティティプロパティタイプ
2つ目の質問は次のとおりです。
Javaではどのデータ型を使用しますか(日付、カレンダー、ロングなど)?
Java側では、Java 8を使用できますLocalDateTime
。レガシーを使用することもできますDate
が、Java 8の日付/時刻型は不変であり、ログに記録するときにタイムゾーンをローカルタイムゾーンにシフトしないため、より優れています。
HibernateでサポートされているJava 8の日付/時刻型の詳細については、こちらの記事をご覧ください。
これで、この質問にも答えることができます。
マッピングにはどのアノテーションを使用し@Temporal
ますか(例:)?
LocalDateTime
またはjava.sql.Timestamp
を使用してタイムスタンプエンティティプロパティをマップする場合@Temporal
、HIbernateはこのプロパティがJDBCタイムスタンプとして保存されることをすでに認識しているため、使用する必要はありません。
を使用している場合のみ、次のように注釈java.util.Date
を指定する必要があります@Temporal
。
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_on")
private Date createdOn;
しかし、次のようにマッピングすると、はるかに優れています。
@Column(name = "created_on")
private LocalDateTime createdOn;
監査列の値を生成する方法
3つ目の質問は次のとおりです。
データベース、ORMフレームワーク(Hibernate)、またはアプリケーションプログラマーの誰がタイムスタンプの設定を担当しますか?
マッピングにはどのアノテーションを使用しますか(例:@Temporal)?
この目標を達成する方法はたくさんあります。データベースにそれを許可することができます。
以下のためにcreate_on
列に、あなたが使用することができますDEFAULT
ように、DDL制約を:
ALTER TABLE post
ADD CONSTRAINT created_on_default
DEFAULT CURRENT_TIMESTAMP() FOR created_on;
updated_on
列については、DBトリガーを使用してCURRENT_TIMESTAMP()
、特定の行が変更されるたびに列の値を設定できます。
または、JPAまたはHibernateを使用して設定します。
次のデータベーステーブルがあるとします。
そして、各テーブルには次のような列があります。
created_by
created_on
updated_by
updated_on
Hibernate @CreationTimestamp
と@UpdateTimestamp
アノテーションの使用
Hibernateは、および列のマッピングに使用できる@CreationTimestamp
および@UpdateTimestamp
アノテーションを提供します。created_on
updated_on
を使用@MappedSuperclass
して、すべてのエンティティによって拡張される基本クラスを定義できます。
@MappedSuperclass
public class BaseEntity {
@Id
@GeneratedValue
private Long id;
@Column(name = "created_on")
@CreationTimestamp
private LocalDateTime createdOn;
@Column(name = "created_by")
private String createdBy;
@Column(name = "updated_on")
@UpdateTimestamp
private LocalDateTime updatedOn;
@Column(name = "updated_by")
private String updatedBy;
//Getters and setters omitted for brevity
}
そして、すべてのエンティティは次のBaseEntity
ようにを拡張します。
@Entity(name = "Post")
@Table(name = "post")
public class Post extend BaseEntity {
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
@OneToOne(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
private PostDetails details;
@ManyToMany
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(
name = "post_id"
),
inverseJoinColumns = @JoinColumn(
name = "tag_id"
)
)
private List<Tag> tags = new ArrayList<>();
//Getters and setters omitted for brevity
}
の使用について詳しくは@MappedSuperclass
、こちらの記事をご覧ください。
しかし、場合でもcreatedOn
及びupdateOn
特性は、Hibernateの固有によって設定される@CreationTimestamp
と@UpdateTimestamp
、注釈createdBy
及びupdatedBy
以下JPA溶液によって示されるように、アプリケーションのコールバックを登録する必要があります。
JPAの使用 @EntityListeners
監査プロパティをEmbeddableにカプセル化できます。
@Embeddable
public class Audit {
@Column(name = "created_on")
private LocalDateTime createdOn;
@Column(name = "created_by")
private String createdBy;
@Column(name = "updated_on")
private LocalDateTime updatedOn;
@Column(name = "updated_by")
private String updatedBy;
//Getters and setters omitted for brevity
}
そして、AuditListener
監査プロパティを設定するを作成します。
public class AuditListener {
@PrePersist
public void setCreatedOn(Auditable auditable) {
Audit audit = auditable.getAudit();
if(audit == null) {
audit = new Audit();
auditable.setAudit(audit);
}
audit.setCreatedOn(LocalDateTime.now());
audit.setCreatedBy(LoggedUser.get());
}
@PreUpdate
public void setUpdatedOn(Auditable auditable) {
Audit audit = auditable.getAudit();
audit.setUpdatedOn(LocalDateTime.now());
audit.setUpdatedBy(LoggedUser.get());
}
}
を登録するAuditListener
には、@EntityListeners
JPAアノテーションを使用できます。
@Entity(name = "Post")
@Table(name = "post")
@EntityListeners(AuditListener.class)
public class Post implements Auditable {
@Id
private Long id;
@Embedded
private Audit audit;
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
@OneToOne(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
private PostDetails details;
@ManyToMany
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(
name = "post_id"
),
inverseJoinColumns = @JoinColumn(
name = "tag_id"
)
)
private List<Tag> tags = new ArrayList<>();
//Getters and setters omitted for brevity
}
JPAでの監査プロパティの実装の詳細については@EntityListener
、チェックアウトこの記事を。