Spring Data Jpaでレコードの登録日時/更新日時を自動で設定する方法

Spring Data Jpaでレコードの登録日時/更新日時を自動で設定する方法をご紹介します。
upsert処理を実現します。

条件

  • Spring Tool Suite 4
  • Spring Boot 2.5.0
  • PostgreSQL 13.3
  • Spring Data Jpa
  • lombok

前提

DBテーブル

以下のようなテーブルを使用します。

CREATE TABLE post
(
    id bigint NOT NULL primary key,
    title character varying(255),
    create_at timestamp NOT NULL,
    update_at timestamp NOT NULL
)

プロジェクトの構成

ここでは、以下のような構成とします。

ソース

model

lombokを使用して、getterやsetterなどのソースはアノテーション指定とします。

登録日時と更新日時を扱うクラスを作成します。

  • @PrePersistを用いて、insert時に登録日時と更新日時に現在日時を設定します。
  • @PreUpdateを用いて、update時に更新日時を設定します。
  • 登録日時のカラムは、updatable = falseとすることで更新時に影響を受けないようにします。

TimeEntity.java

package com.example.model;

import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@MappedSuperclass
public class TimeEntity {
    @Column(name = "create_at", updatable = false)
    private Timestamp createAt;

    @Column(name = "update_at")
    private Timestamp updateAt;

    @PrePersist
    public void onPrePersist() {
        setCreateAt(new Timestamp(System.currentTimeMillis()));
        setUpdateAt(new Timestamp(System.currentTimeMillis()));
    }

    @PreUpdate
    public void onPreUpdate() {
        setUpdateAt(new Timestamp(System.currentTimeMillis()));
    }
}

登録日時と更新日時を扱うクラスを継承します。

Post.java

package com.example.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "post")
public class Post extends TimeEntity {
    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "title")
    private String title;
}

repository

PostRepository.java

package com.example.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.model.Post;

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {

}

service

今回使用するメソッドは、以下のうちupsert()のみです。

PostService.java

package com.example.service;

import java.util.Optional;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.model.Post;
import com.example.repository.PostRepository;

@Service
@Transactional
public class PostService {
    @Autowired
    PostRepository postRepository;

    /**
     * IDを指定して対象レコードを取得する
     * 
     * @param id
     * @return
     */
    public Optional<Post> findById(Long id) {

        return postRepository.findById(id);
    }

    /**
     * レコードを追加または更新する
     * 
     * @param post
     */
    public void upsert(Post post) {

        postRepository.save(post);
    }

    /**
     * IDを指定して対象レコードを削除する
     * 
     * @param id
     */
    public void delete(Long id) {

        postRepository.deleteById(id);
    }
}

controller

PostServiceを持いて、レコードのupsertを行います。

  • 登録日時と更新日時以外のデータを指定します。
  • 登録日時と更新日時はプログラム任せです。
package com.example.controller;

import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.model.Post;
import com.example.service.PostService;

@RestController
public class TestController {

    @Autowired
    PostService postService;

    @GetMapping(path = "/test")
    public String getTest(HttpServletRequest request) {

        postService.upsert(new Post(Long.valueOf(11), "test"));

        return "Hello World!";
    }
}

実行結果

初回

登録日時と更新日時が自動で設定されました。

2回目(更新)

以下のようにして、レコードを更新します。

postService.upsert(new Post(Long.valueOf(11), "testUpdate!!!"));

レコードが更新され、登録日時はそのままで、更新日時が更新されていることがわかります。

参考

Qiita:JPAでEntityを親クラスと子クラスに分ける方法

https://qiita.com/zateon/items/924ad592c7c94dee4381

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です