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

