タイトルの通り、レコードの作成日時と更新日時を自動設定してみる。
article.setCreatedDatetime(new Date()); article.setUpdatedDatetime(new Date());
こういうのを都度書くのはバカバカしいのでJPAに自動的に設定されるようにします。
Table 適当なテーブルを作ります。
$ mysql --version mysql Ver 15.1 Distrib 5.5.52-MariaDB, for Linux (x86_64) using readline 5.1 DROP TABLE article; CREATE TABLE IF NOT EXISTS article ( id INT(11) NOT NULL AUTO_INCREMENT, title VARCHAR(50) DEFAULT NULL, created_datetime DATETIME NOT NULL, updated_datetime DATETIME NOT NULL, PRIMARY KEY(id) );
Entity EntityはAbstractEntityに日時を自動更新する仕組みを持って、継承して使うようにします。
まず全てのentityの親となるEntityを作ります。
作成前、更新前などの永続化処理にフックするためのアノテーションがあるのでそれを使います。
annotation
備考
@PrePersist
永続化前に実行
@PostPersist
永続化後に実行
@PreUpdate
更新処理前に実行
@PostUpdate
更新処理後に実行
@PreRemove
削除前に実行
@PostRemove
削除後に実行
@PreLoad
読み込み前に実行
@PostLoad
読み込み後に実行
永続化前と更新前に処理を実行したいので、 @PrePersist
と @PreUpdate
を使ってみます。
@Getter @Setter @MappedSuperclass public class AbstractEntity { @Column(name = "created_datetime") private Date createdDatetime; @Column(name = "updated_datetime") private Date updatedDatetime; @PrePersist public void onPrePersist() { setCreatedDatetime(new Date()); setUpdatedDatetime(new Date()); } @PreUpdate public void onPreUpdate() { setUpdatedDatetime(new Date()); } }
AbstractEntity
を継承した適当なクラスを作ります。
@Setter @Getter @Entity(name = "article") public class Article { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(name = "title") private String title; }
Repository repositoryを追加します。
@Repository public interface ArticleRepository extends JpaRepository<Article, Long> { }
Test @PrePersist
の動作を確認するためCreatedDatetime
とUpdatedDatetime
を指定せず書き込んでみます。
@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class) public class ArticleRepositoryTest { @Autowired private ArticleRepository articleRepository; @Test public void testCreateArticle() { Article article = new Article(); article.setTitle("title1"); articleRepository.saveAndFlush(article); } }
確認。
MariaDB [sample]> SELECT * FROM article; +----+--------+---------------------+---------------------+ | id | title | created_datetime | updated_datetime | +----+--------+---------------------+---------------------+ | 1 | title1 | 2017-09-08 01:28:51 | 2017-09-08 01:28:51 | +----+--------+---------------------+---------------------+ 1 row in set (0.00 sec)
超簡単ですね。
次は@PreUpdate
。
@Test public void testCreateArticle() throws InterruptedException { Article article = new Article(); article.setTitle("title2"); article = articleRepository.saveAndFlush(article); Thread.sleep(2000); articleRepository.saveAndFlush(article); }
Updateだけ確認するために2000ms間Sleepして実行した後に確認すると。
MariaDB [sample]> SELECT * FROM article; +----+--------+---------------------+---------------------+ | id | title | created_datetime | updated_datetime | +----+--------+---------------------+---------------------+ | 1 | title1 | 2017-09-08 01:28:51 | 2017-09-08 01:28:51 | | 3 | title2 | 2017-09-08 01:45:02 | 2017-09-08 01:45:04 | +----+--------+---------------------+---------------------+
いい感じですね。
MariaDBの機能で実現 最新版のMariaDBにCURRENT_TIMESTAMP
とUPDATE CURRENT_TIMESTAMP
があるらしくアプリ側で設定しなくても自動的に書き込めるらしい。
MariaDB 5.5.52では使えなかった。5.6以上で使えるかもしれない。(調べていない。)
CREATE TABLE IF NOT EXISTS article ( id INT(11) NOT NULL AUTO_INCREMENT, title VARCHAR(50) DEFAULT NULL, created_datetime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_datetime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY(id) );
参考
https://mariadb.com/kb/en/the-mariadb-library/timestamp/