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!!!"));
レコードが更新され、登録日時はそのままで、更新日時が更新されていることがわかります。