Spring Dataを使って、自動的に監査証跡を保存する
業務アプリケーションを作っていると、監査証跡ということで、作成者、作成日時、更新者、更新日時を保存するということがあると思います。Spring Dataのアノテーションを使うと、自動でセットしてくれるので、アプリケーションで決まりきったコードを書かなくて済むということみたいです。
Task.java(モデルクラス)
package sample.model; import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import java.util.Date; @Entity @EntityListeners(value = AuditingEntityListener.class) public class Task { @Id @GeneratedValue private Long id; private String taskName; @CreatedBy private String createdBy; @Temporal(TemporalType.TIMESTAMP) @CreatedDate private Date createdDate; @LastModifiedBy private String modifiedBy; @Temporal(TemporalType.TIMESTAMP) @LastModifiedDate private Date modifiedDate; public Task() { } @Override public String toString() { return "Task{" + "id=" + getId() + ", taskName='" + getTaskName() + '\'' + ", createdBy='" + getCreatedBy() + '\'' + ", createdDate=" + getCreatedDate() + ", modifiedBy='" + getModifiedBy() + '\'' + ", modifiedDate=" + getModifiedDate() + '}'; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTaskName() { return taskName; } public void setTaskName(String taskName) { this.taskName = taskName; } public String getCreatedBy() { return createdBy; } public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } public Date getCreatedDate() { return createdDate; } public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; } public String getModifiedBy() { return modifiedBy; } public void setModifiedBy(String modifiedBy) { this.modifiedBy = modifiedBy; } public Date getModifiedDate() { return modifiedDate; } public void setModifiedDate(Date modifiedDate) { this.modifiedDate = modifiedDate; } }
StartupRunner.java(呼び側)
package sample; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import sample.jpa.TaskRepository; import sample.model.Task; public class StartupRunner implements CommandLineRunner { protected final Log logger = LogFactory.getLog(getClass()); @Autowired private TaskRepository taskRepository; @Override public void run(String... args) throws Exception { // Generate a new record. Task task = new Task(); task.setTaskName("task1"); Task savedTask = taskRepository.save(task); System.out.println(savedTask); Thread.sleep(1000); // Update the record after 1sec. savedTask.setTaskName("task2"); Task savedTask2 = taskRepository.save(savedTask); System.out.println(savedTask2); } }
AuditingConfig(監査証跡の設定クラス)
package sample.jpa; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.domain.AuditorAware; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @EnableJpaAuditing @Configuration public class AuditingConfig { @Bean public AuditorAware<String> createAuditorProvider() { return new SecurityAuditor(); } @Bean public AuditingEntityListener createAuditingListener() { return new AuditingEntityListener(); } public static class SecurityAuditor implements AuditorAware<String> { @Override public String getCurrentAuditor() { return "taka2"; } } }
実行結果(抜粋)
Task{id=1, taskName='task1', createdBy='taka2', createdDate=Sat Jul 23 23:38:44 JST 2016, modifiedBy='taka2', modifiedDate=Sat Jul 23 23:38:44 JST 2016} Task{id=1, taskName='task2', createdBy='taka2', createdDate=Sat Jul 23 23:38:44 JST 2016, modifiedBy='taka2', modifiedDate=Sat Jul 23 23:38:45 JST 2016}
呼び側ではtaskNameしかセットしていませんが、createdBy/createdDate/modifiedBy/modifiedDateの各フィールドがセットされていますね。サンプルなので、ユーザは固定の文字列返してますが、webアプリケーションなら、ログインユーザを返すところでしょうね。