JPA Auditingとは

# JPA Auditingとは
JPAを使用してDomainをRDBSのテーブルにマッピングする際、共通的にDomainを持っているフィールドやカラムが存在します。

代表的には以下となります。

- CreateDate
- UpdateDate
- 識別子

のようなフィールドおよびカラムがありますよね。 
Domainごとに存在するということはコードが重複されていることでしょう。
データベースを誰が、いつ作成したのかなど記録を残したほうがメンテナンスにも役に立つためです。
そのため、生成日、修正日のようなカラムは本当に重要なデータです。

それでJPAではAuditという機能を提供しています。Auditは監視するという意味でSpring Data JPAで時間に対して自動的に値を入れてくれる機能です。ドメインを永続性コンテキストに保存したり照会などを行ってからupdateを行う場合、毎回時間データを入力しなければならないのですが、auditを利用することで自動的に時間をマッピングしデータベースのテーブルに入れてくれます。

# 練習
1．domain package内にBaseTimeEntityクラスを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684074/0dc150b0-ed54-7778-6641-273bc3eb6ee8.png)

2．BaseTimeEntityを以下のように作成します。

```java

package jojoidu.boot.springboot.domain;

import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity {

    @CreatedDate
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime modifiedDate;
}

```
BaseTimeEntityクラスはすべてのEntityクラスの親クラスになり、**EntityクラスのcreatedDate、modifiedDateを自動で管理する役割をします。**

- ＠MappedSuperclass 
    - JPA EntityクラスがBaseTimeEntityを継承する場合フィールド（createdDate、modifiedDate）もカラムとして認識されるようにします。

- ＠EntityListeners(AuditingEntityListener.class)
    - BaseTimeEntityクラスにAuditing機能を与えます。

- ＠CreatedDate
    - Entityが生成され、保存されるとき時間が自動に保存されます。

- ＠LastModifiedDate
    - 照会したEntityの値を変更する際、時間が自動に保存されます。

3．EntityクラスにBaseTimeEntityクラスを継承します。

```java

package jojoidu.boot.springboot.domain.posts;

import jojoidu.boot.springboot.domain.BaseTimeEntity;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Getter
@NoArgsConstructor
@Entity // テーブルとリンクされるクラスを示す
public class Posts extends BaseTimeEntity {

    @Id // PKフィールドを示す
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(length = 500, nullable = false)
    private String title;

    @Column(columnDefinition = "TEXT", nullable = false)
    private String content;

    private String author;

    @Builder
    public Posts(String title, String content, String author) {
        this.title = title;
        this.content = content;
        this.author = author;
    }

    public void update(String title, String content) {
        this.title = title;
        this.content = content;
    }
}


```

4．最後にJPA Auditingアノテーションが活性化されるようにmainクラスに活性化アノテーションを追加します。

```java

package jojoidu.boot.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
```

# テスト
テストは欠かせないので、テストメソッドも追加してみました。

```java

@Test
    public void saveBaseTimeEntity() {
        // given
        LocalDateTime now = LocalDateTime.of(2020, 8,12,0,0,0);
        postsRepository.save(Posts.builder()
        .title("title")
        .content("content")
        .author("author")
        .build());

        // when
        List<Posts> postsList = postsRepository.findAll();

        //then
        Posts posts = postsList.get(0);

        System.out.println(">>>>>>>createdDate=" + posts.getCreatedDate() + ", modifiedDate=" + posts.getModifiedDate());

        assertThat(posts.getCreatedDate()).isAfter(now);
        assertThat(posts.getModifiedDate()).isAfter(now);
    }
```
### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684074/5f94d826-f52a-6f44-ec18-11f92df23cf1.png)
正常に動くことを確認できました。
こんな楽ってうれしすぎるんですね。