JPAで最終更新情報の更新を自動化して画面に表示するまで

# はじめに
* 各バージョン

|     projects    |    version    |
|:---------------:|:-------------:|
|  spring-security|  4.1.1.RELEASE|
|  spring-data-jpa| 1.10.2.RELEASE|
|        thymeleaf|  2.1.5.RELEASE|

# やりたいこと
* DBへのinsert/update時に登録情報、最終更新情報をコーディング無しで自動更新されるようにする。
* entityの日付型はjava8のlocalDatetimeを使用する。
* 登録/更新者はログイン情報から取得する。
* thymeleafをlocalDatetimeに対応させる。

# JPAのjava8日付型対応
* 登録/更新日にjava8日付型を使用したいので設定をします。
* Spring Data JPAでは設定をしないと日付型を使用できないようです。   
詳しくはコチラ。大変参考になりました。   
[Spring Boot環境でJava8日付型(JSR-310)を使うための設定](http://qiita.com/tag1216/items/25a64bba2bde98ea88d3)

```java:Application.java
@SpringBootApplication
@EntityScan(basePackageClasses = {Application.class, Jsr310JpaConverters.class})
public class Application {
```

# 更新情報の自動更新
* Entityにリスナーとアノテーションを設定します。

```java:Vendor.java
@Data
@Entity
@EntityListeners(AuditingEntityListener.class)  --(1)
public class Vendor implements Serializable {
	@Id
	@Column(name="vendor_id")
	private int vendorId;

	@Column(name="vendor_name")
	private int vendorName;

	@CreatedBy  --(2)
	@Column(name="created_by")
	private String createdBy;
	
	@CreatedDate  --(3)
	@Column(name="created_on")
	private LocalTime createdOn;

	@LastModifiedBy  --(2)
	@Column(name="updated_by")
	private String updatedBy;
	
	@LastModifiedDate  --(3)
	@Column(name="updated_on")
	private LocalTime updatedOn;
}
```

### (1) AuditingEntityListener
* 自動更新させたいentityに付与します。コレを付与することでinsert/update時にウマイことやってくれます。
* 各Entityに付与するのではなく一括で設定するにはxmlを用意する必要がありそうです。   
[5.10.1. General auditing configuration](http://docs.spring.io/spring-data/jpa/docs/1.10.2.RELEASE/reference/html/#jpa.auditing.configuration)

### (2) 登録/更新者
* `@CreatedBy`、`@LastModifiedBy`を付与したカラムには「誰が」の情報が自動的に登録されます。登録される内容に関しては後述。

### (3) 登録/更新日時
* `@CreatedDate`、`@LastModifiedDate`を付与したカラムには「いつ」の情報が自動的に登録されます。
* 今回はJSR-310を使用していますが、その他にもJodaTimesのDateTime、レガシーな JavaのDate、Calendar、long/Longを使用することができます。

# 登録/更新者の取得
* Spring-Securityを使用している場合、以下のようにしてログインユーザーを登録/更新者としてあてこむ事ができます。
* まずログインユーザー名取得クラスを実装します。User型でも大丈夫っぽいですが、今回はStringで取得してます。implementsの型とメソッドの戻り値の型を統一してください。

```java:SpringSecurityAuditorAware.java
public class SpringSecurityAuditorAware implements AuditorAware<String> {
	@Override
	public String getCurrentAuditor() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication == null || !authentication.isAuthenticated()) {
			return null;
		}

		return ((MyUserDetails) authentication.getPrincipal()).getUsername();
	}
}
```

* 実装したクラスをbean定義に追加します。   
`@EnableJpaAuditing`を忘れずに。

```java:SpringSecurityAuditorAwareConfig.java
@Configuration
@EnableJpaAuditing
public class SpringSecurityAuditorAwareConfig {
	@Bean
	public AuditorAware<String> auditorProvider() {
		return new SpringSecurityAuditorAware();
	}
}
```

# Thymeleafのjava8日付型対応
* JSR310はthymeleafでもそのまま使用できないので、もろもろ設定していきます。readmeの[Requirements](https://github.com/thymeleaf/thymeleaf-extras-java8time#requirements-30x)に必要要件は3.0.0以上と書いてありましたが、2.1.5でもうごきました。

* まず依存関係を追加します。

```
<dependency>
	<groupId>org.thymeleaf.extras</groupId>
	<artifactId>thymeleaf-extras-java8time</artifactId>
	<version>2.1.0.RELEASE</version>
</dependency>
```

* readmeの[installation](https://github.com/thymeleaf/thymeleaf-extras-java8time#installation)に沿って`Java8TimeDialect`を適用するbean定義を追加します。

```java:JavaConfig.java
@Configuration
public class JavaConfig {
	
	/**
	 * thtmeleafでjava8の日付API使うための設定
	 * @see https://github.com/thymeleaf/thymeleaf-extras-java8time
	 * @return
	 */
	@Bean
	public TemplateEngine templateEngin() {
		TemplateEngine templateEngine = new TemplateEngine();
		templateEngine.addDialect(new Java8TimeDialect());
		return templateEngine;
	}
}
```

* 公式のチュートリアルには使い方が載ってないのですが、readmeに[usage](https://github.com/thymeleaf/thymeleaf-extras-java8time#usage)が書いてあるのでコレを参考にコーディングしていきます。雰囲気、こんな感じ。

```
<p th:text="${#temporals.format(hogeForm.updatedOn, 'yyyy-MM-dd HH:mm')}" class="form-control-static">-</p>
```