DockerにPostgre環境を作ってSpring bootで利用する

Springbootの勉強のため、Dockerで作成したPostgre環境に接続してアプリケーションを作成します。


環境：Windows10
sts-4.10.0.RELEASE
Docker version 20.10.6
docker-compose version 1.29.1

→この記事のGitHubリポジトリ
https://github.com/jirentaicho/springbootsample
ブランチ:qiita

※docker-compose.ymlなどはdevフォルダに格納しております。


最終的なフォルダ構成

<details><summary>フォルダ構成をみる</summary><div>
<pre>
C:.
│  .classpath
│  .gitignore
│  .project
│  HELP.md
│  mvnw
│  mvnw.cmd
│  pom.xml
│  readme.md
│
├─.mvn
│  └─wrapper
│          maven-wrapper.jar
│          maven-wrapper.properties
│          MavenWrapperDownloader.java
│
├─.settings
│      org.eclipse.core.resources.prefs
│      org.eclipse.jdt.apt.core.prefs
│      org.eclipse.jdt.core.prefs
│      org.eclipse.m2e.core.prefs
│      org.eclipse.wst.common.component
│      org.eclipse.wst.common.project.facet.core.xml
│      org.eclipse.wst.validation.prefs
│      org.springframework.ide.eclipse.prefs
│
├─dev
│  │  docker-compose.yml
│  │
│  └─postgres
│      └─setup
│              1-ddl.sql
│              2-dml.sql
│
├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─volkruss
│  │  │          │  AnicomApplication.java
│  │  │          │  ServletInitializer.java
│  │  │          │
│  │  │          ├─application
│  │  │          │  ├─controller
│  │  │          │  │      InitializeController.java
│  │  │          │  │      RegisterController.java
│  │  │          │  │
│  │  │          │  └─request
│  │  │          │          AnimationRequest.java
│  │  │          │
│  │  │          ├─domain
│  │  │          │  ├─entity
│  │  │          │  │      AnimationEntity.java
│  │  │          │  │      AnimationRepository.java
│  │  │          │  │
│  │  │          │  ├─mapper
│  │  │          │  │  │  AnimationMapper.java
│  │  │          │  │  │
│  │  │          │  │  └─impl
│  │  │          │  │          AnimationMapperImpl.java
│  │  │          │  │
│  │  │          │  ├─model
│  │  │          │  │      Animation.java
│  │  │          │  │
│  │  │          │  └─service
│  │  │          │      │  AnimationService.java
│  │  │          │      │
│  │  │          │      └─Impl
│  │  │          │              AnimationServiceImpl.java
│  │  │          │
│  │  │          └─infrastructure
│  │  │              └─repository
│  │  │                      AnimationJpaRepository.java
│  │  │                      AnimationRepositoryImpl.java
│  │  │
│  │  ├─resources
│  │  │  │  application.properties
│  │  │  │
│  │  │  ├─static
│  │  │  └─templates
│  │  │          index.html
│  │  │          register.html
│  │  │
│  │  └─webapp
│  └─test
│      └─java
│          └─com
│              └─volkruss
│                      AnicomApplicationTests.java
│
└─target
    ├─classes
    │  │  application.properties
    │  │
    │  ├─com
    │  │  └─volkruss
    │  │      │  AnicomApplication.class
    │  │      │  ServletInitializer.class
    │  │      │
    │  │      ├─application
    │  │      │  ├─controller
    │  │      │  │      InitializeController.class
    │  │      │  │      RegisterController.class
    │  │      │  │
    │  │      │  └─request
    │  │      │          AnimationRequest.class
    │  │      │
    │  │      ├─domain
    │  │      │  ├─entity
    │  │      │  │      AnimationEntity.class
    │  │      │  │      AnimationRepository.class
    │  │      │  │
    │  │      │  ├─mapper
    │  │      │  │  │  AnimationMapper.class
    │  │      │  │  │
    │  │      │  │  └─impl
    │  │      │  │          AnimationMapperImpl.class
    │  │      │  │
    │  │      │  ├─model
    │  │      │  │      Animation.class
    │  │      │  │
    │  │      │  └─service
    │  │      │      │  AnimationService.class
    │  │      │      │
    │  │      │      └─Impl
    │  │      │              AnimationServiceImpl.class
    │  │      │
    │  │      └─infrastructure
    │  │          └─repository
    │  │                  AnimationJpaRepository.class
    │  │                  AnimationRepositoryImpl.class
    │  │
    │  └─templates
    │          index.html
    │          register.html
    │
    ├─generated-sources
    │  └─annotations
    ├─generated-test-sources
    │  └─test-annotations
    ├─m2e-wtp
    │  └─web-resources
    │      └─META-INF
    │          │  MANIFEST.MF
    │          │
    │          └─maven
    │              └─com.volkruss
    │                  └─anicom
    │                          pom.properties
    │                          pom.xml
    │
    └─test-classes
        └─com
            └─volkruss
                    AnicomApplicationTests.class

</pre>
</div></details>


## Postgre環境の準備

Dockerを使ってpostgre環境を準備します。以前仕事では共通のDBサーバーがあって、スキーマを作るなどしてみんなで同じものを共有していました。
しかし、ある時から個人のローカルにDockerでDB環境作るようになってから、お構いなしにDBをぶっ壊したりしていました。

というわけでDockerでPostgre環境を用意します。

```yml:docker-compose.yml
version: '3'
services:
    postgre:
        image: postgres:latest
        ports:
            - 5432:5432
        container_name: my_postgre
        volumes:
        - ./postgres/data:/var/lib/postgresql/data
        # 初期化用のシェルを格納しておきます。
        - ./postgres/setup:/docker-entrypoint-initdb.d
        environment: 
            POSTGRES_USER: misaka
            POSTGRES_PASSWORD: mikoto

```

最初にsqlを実行するdocker-entrypoint-initdb.dに対して、postgres/setupフォルダをマウントしています。ここにsqlファイルを置くと最初に実行されます。
先頭に番号を振って実行順番を制御しています。

もし、Postgre環境を作り直したい時は以下のフォルダを削除します。
./postgres/data
（権限で消せないとか出たらpowershellで消してあげます rm -r data)

以下のコマンドでコンテナを立ち上げます

    docker-compose up -d


## STSでプロジェクト作成

以下のようにプロジェクトを作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/fcf0a6fb-e5ad-9716-3e77-3891cb266690.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/c5df271a-f73a-c846-b2c5-7e48e544c98a.png)

#### データベースの接続設定

以下のファイルを修正して、コンテナのPostgreデータベースに接続するようにします。
anicom\src\main\resources\application.properties


    spring.datasource.driver-class-name=org.postgresql.Driver
    spring.datasource.url=jdbc:postgresql://localhost:5432/misaka
    spring.datasource.username=misaka
    spring.datasource.password=mikoto


#### Viewを表示する

今、プロジェクトを実行すると、リクエストに対して何の設定も行っていないため、以下のようなページが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/b64f5a52-2cd6-6ede-05df-296c2eb51edc.png)


まずは/にアクセスしたときにページを表示させるようにしていきます。

controllerの作成を行います。
controllerクラスには@Controllerアノテーションを付けます。このアノテーションをつけることで、HTMLなどのViewを返すことができます。
今回は/にアクセスしたときに、index.htmlを返すようにしています。

```java:InitializeController.java
package com.volkruss.application.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class InitializeController {
	
	@GetMapping("/")
	public String getIndex() {
		return "index";
	}
}
```

index.htmlを作成します。
anicom\src\main\resources\templates\index.html

```html:index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>アニメコム</title>
</head>
<body>
	<p>お気に入りのアニメとキャラクターを登録しよう</p>
</body>
</html>
```

これで実行すると以下のような画面が表示されています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/9f185425-b31d-0f20-73c7-ff196ae38269.png)


リクエストの情報をコントローラーが受け取ってViewを返すということができるようになりました。


#### データベースのレコードを表示する

次はデータベースからレコードを取得して、表示させます。
EntityととRepositoryとModelを作成します。

##### 設定の見直し

Entityは実際のテーブルの構造と紐づいていますので、そのままテーブルの構造を反映させます。
アクセサについては簡略化させたいので、lombokを利用します。pom.xmlに以下を追加します。
あと、プロジェクト作成時にJPAを追加してなかったので、jpaの依存も追加します。

```xml:pom.xml
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- 追加 -->
		<dependency>
		    <groupId>org.projectlombok</groupId>
		    <artifactId>lombok</artifactId>
		    <version>1.18.8</version>
		    <scope>provided</scope>
		</dependency>
		<!-- もう一個追加 -->
		<dependency>
        	<groupId>org.springframework.boot</groupId>
        	<artifactId>spring-boot-starter-data-jpa</artifactId>
    	</dependency>
	</dependencies>
```

SpringToolSuite4.iniに以下を追記します。

    -javaagent:lombokのパス\lombok.jar
    -vmarges -javaagent:lombok.jar

#### Entityの作成

ようやくEntityクラスを作成できます。テーブルの構造と紐づけたいので以下のようにします。


```java:AnimationEntity.java
package com.volkruss.domain.entity;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
@Entity
@Table(name = "m_animation")
public class AnimationEntity{
	
	@Id
	@Column(name = "id")
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "m_animation_id_seq")
	@SequenceGenerator(name = "m_animation_id_seq",sequenceName = "m_animation_id_seq",initialValue = 1,allocationSize = 1)
	private int id;
	
	@Column(name = "title")
	private String title;
	
	@Column(name = "broadcast_start")
	private Date broadcast_start;
	
	@Column(name = "broadcast_end")
	private Date broadcast_end;
	
	@Column(name = "created_at")
	private Date created_at;
	
	@Column(name = "updated_at")
	private Date updated_at;
}

```

##### Modelの作成

続いてModelを作成します。現在放送中かどうかを返せるようなメソッドを定義しました。

```java:Animation.java
package com.volkruss.domain.model;

import java.util.Date;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class Animation {

	private int id;
	
	private String title;
	
	private Date broadcast_start;
	
	private Date broadcast_end;
	
	/**
	 * <P>
	 * 現在放送中かどうかを返します。
	 * </p>
	 * 
	 * @return　放送期間が現在時刻の範囲ならばTrue / そうでない場合はfalse
	 */
	public boolean isBroadNow() {
		//　日付の範囲内の場合True
		Date today = new Date();
		return today.after(broadcast_start) && today.before(broadcast_end);
	}
}

```

#### Repositoryの作成

AnimationEntityを取得するJpaRepositoryを継承したAnimationJpaRepositoryインターフェースを作成します。必要最低限のデータアクセスに関するメソッドが提供されているので、こちらを利用します。

そして、AnimationJpaRepositoryを利用するAnimationRepositoryを作成します。
AnimationJpaRepositoryから取得したEntityをModelに変換して返却します。
この時に変換するのにAnimationMapperクラスを用意します。


###### AnimationJpaRepositoryの作成

SQL文を書かなくてもEntityを利用することでデータアクセスができるようになります。
そのために、JpaRepositoryを継承したインターフェースを作成します。

```java:AnimationJpaRepository.java
package com.volkruss.infrastructure.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.volkruss.domain.entity.AnimationEntity;

public interface AnimationJpaRepository extends JpaRepository<AnimationEntity,String>{
	
}
```


###### AnimationRepositoryの作成

AnimationJpaRepositoryとAnimationMapperを利用して、Animationモデルを返すクラスです。
インターフェースは適宜作成しておきます。

```java:AnimationRepositoryImpl.java
package com.volkruss.infrastructure.repository;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.volkruss.domain.entity.AnimationEntity;
import com.volkruss.domain.entity.AnimationRepository;
import com.volkruss.domain.mapper.AnimationMapper;
import com.volkruss.domain.model.Animation;

@Repository
public class AnimationRepositoryImpl implements AnimationRepository {

	@Autowired
	private AnimationJpaRepository animationJpaRepository;
	
	@Autowired
	private AnimationMapper animationMapper;
	
	@Override
	public List<Animation> getAll() {
		List<AnimationEntity> lists = animationJpaRepository.findAll();
		return lists.stream().map(animationMapper::toAnimation).collect(Collectors.toList());
	}
}
```

###### AnimationMapperの作成

EntityをModelに変換するクラスを作成します。
こちらもインターフェースを適宜作成しておきます。

```java:AnimationMapperImpl.java
package com.volkruss.domain.mapper.impl;

import org.springframework.stereotype.Component;

import com.volkruss.domain.entity.AnimationEntity;
import com.volkruss.domain.mapper.AnimationMapper;
import com.volkruss.domain.model.Animation;

@Component
public class AnimationMapperImpl implements AnimationMapper{

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Animation toAnimation(AnimationEntity entity) {
		Animation animation = new Animation();
		animation.setTitle(entity.getTitle());
		animation.setBroadcast_start(entity.getBroadcast_start());
		animation.setBroadcast_end(entity.getBroadcast_end());
		return animation;
	}
}
```

#### Serviceの作成

今回は取得するだけなので、repositoryからモデルを取得します。

```java:AnimationServiceImpl.java
package com.volkruss.domain.service.Impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.volkruss.domain.entity.AnimationRepository;
import com.volkruss.domain.model.Animation;
import com.volkruss.domain.service.AnimationService;

@Service
public class AnimationServiceImpl implements AnimationService{

	@Autowired
	private AnimationRepository animationRepository; 
	
	@Override
	public List<Animation> getAnimationList() {
		return animationRepository.getAll();
	}
}
```

#### コントローラーの修正

controllerからserviceを利用してモデルを取得して、その結果をViewに反映させるように修正します。

```java:InitializeController.java
package com.volkruss.application.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.volkruss.domain.model.Animation;
import com.volkruss.domain.service.AnimationService;

@Controller
public class InitializeController {
	
	@Autowired
	private AnimationService animationService;
	
	@GetMapping("/")
	public String getIndex(Model model) {
		List<Animation> animations = animationService.getAnimationList();
		//　modelに値を設定してViewで利用できるようなる
		model.addAttribute("animations",animations);
		return "index";
	}
}
```

#### Viewの修正

Animationモデルを受けっているので、Viewで表示していきます。
モデルのisBroadNowメソッドを利用して、放送中かどうかを判定しています。

```html:index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>アニメコム</title>
</head>
<body>
	<p>お気に入りのアニメとキャラクターを登録しよう</p>
	<table>
	    <thead>
	        <tr>
	            <th colspan="2">アニメ情報</th>
	        </tr>
	    </thead>
	    <tbody　th:each="animation : ${animations}">
	        <tr>
	        	<td:block th:if="${animation.isBroadNow()}">
				  <td　th:text="放送中">放送中</td>
				</td:block>
				<td:block th:if="${!animation.isBroadNow()}">
				  <td　th:text="放送していません">放送していません</td>
				</td:block>
	            <td　th:text="${animation.title}">タイトル</td>
	            <td　th:text="${#strings.substring(animation.broadcast_start,0,10)}">放送開始日</td>
	        </tr>
	    </tbody>
	</table>
</body>
</html>
```

以下のように表示されていれば、データベースからレコードを取得して、Viewに表示するというところまでできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/ecd3933b-4306-2b1c-0518-8f3c0d4e33e6.png)

見た目も素晴らしいですね（笑）

### 登録処理を作成する

サクッと登録処理を作成します。


#### コントローラーの修正

コントローラーに登録時ページへのマッピング情報を追加します。
モデルにリクエストクラスのインスタンスを設定しています。
このリクエストクラスは、HTMLのフォームの内容と紐づいております。

```java:InitializeController.java
package com.volkruss.application.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.volkruss.application.request.AnimationRequest;
import com.volkruss.domain.model.Animation;
import com.volkruss.domain.service.AnimationService;

@Controller
public class InitializeController {
	
	@Autowired
	private AnimationService animationService;
	
	@GetMapping("/")
	public String getIndex(Model model) {
		List<Animation> animations = animationService.getAnimationList();
		//　modelに値を設定してViewで利用できるようなる
		model.addAttribute("animations",animations);
		return "index";
	}
	
	//追加
	@GetMapping("/register")
	public String getRegister(Model model) {
		model.addAttribute("animationReqeust", new AnimationRequest());
		return "register";
	}
}
```

#### リクエストクラスの作成


formに紐づくリクエストクラスを作成します。

```java:
package com.volkruss.application.request;

import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Setter
@Getter
@NoArgsConstructor
public class AnimationRequest {
	
	private String title;
	
	@DateTimeFormat(pattern = "yyyy-MM-dd")
	private Date broadcast_start;
	
	@DateTimeFormat(pattern = "yyyy-MM-dd")
	private Date broadcast_end;
}
```

#### Viewの作成

register.htmlを追加します。ここでformを作成してPOSTにてデータを送信できるようにします。

```html:register.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>アニメコム</title>
</head>
<body>

	<form th:action="@{register}" th:object="${animationReqeust}" method="POST" >
		<div>
			<label>タイトル</label>
			<input type="text" th:field="*{title}" required>
		</div>
		
		<div>
			<label>放送開始</label>
			<input type="date" th:field="*{broadcast_start}" required>
		</div>
		
		<div>
			<label>放送終了</label>
			<input type="date" th:field="*{broadcast_end}" required>
		</div>
		
		<button type="submit">登録する</button>
	</form>

</body>
</html>
```

ついでにこのViewへのリンクをindex.htmlに作成します。

```html:index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>アニメコム</title>
</head>
<body>
	<p>お気に入りのアニメとキャラクターを登録しよう</p>
	<table>
	    <thead>
	        <tr>
	            <th colspan="2">アニメ情報</th>
	        </tr>
	    </thead>
	    <tbody　th:each="animation : ${animations}">
	        <tr>
	        	<td:block th:if="${animation.isBroadNow()}">
				  <td　th:text="放送中">放送中</td>
				</td:block>
				<td:block th:if="${!animation.isBroadNow()}">
				  <td　th:text="放送していません">放送していません</td>
				</td:block>
	            <td　th:text="${animation.title}">タイトル</td>
	            <td　th:text="${#strings.substring(animation.broadcast_start,0,10)}">放送開始日</td>
	        </tr>
	    </tbody>
	</table>
	<!-- 追加 -->
	<a href="/register" th:href="@{/register}">新規登録する</a>
</body>
</html>
```

#### コントローラーの作成

次にformの値を受け取る必要があるのでコントローラーを新しく作成します。
今回は妥当性確認処理などを省いて、フォームからの値を登録してトップページにリダイレクトさせています。

```java:RegisterController.java
package com.volkruss.application.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;

import com.volkruss.application.request.AnimationRequest;
import com.volkruss.domain.service.AnimationService;

@Controller
public class RegisterController {
	
	@Autowired
	private AnimationService animationService;

	@PostMapping("/register")
	public String register(AnimationRequest request,Model model) {
		animationService.insert(request);
		return "redirect:/";
	}
	
}
```

### 登録ロジックの作成

insert処理を作成します。
まずはserviceクラスを修正します。

モデルを作成してrepositoryに渡します。

```java:AnimationServiceImpl.java
package com.volkruss.domain.service.Impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.volkruss.application.request.AnimationRequest;
import com.volkruss.domain.entity.AnimationRepository;
import com.volkruss.domain.model.Animation;
import com.volkruss.domain.service.AnimationService;

@Service
public class AnimationServiceImpl implements AnimationService{

	@Autowired
	private AnimationRepository animationRepository; 
	
	@Override
	public List<Animation> getAnimationList() {
		return animationRepository.getAll();
	}

	//　追加
	@Override
	public void insert(AnimationRequest request) {
		Animation animation = create(request);
		animationRepository.insert(animation);
	}
	
	// 追加
	/**
	 * <P>
	 * リクエストからモデルを作成します。
	 * </P>
	 * @param request
	 * @return
	 */
	private Animation create(AnimationRequest request) {
		Animation animation = new Animation();
		animation.setTitle(request.getTitle());
		animation.setBroadcast_start(request.getBroadcast_start());
		animation.setBroadcast_end(request.getBroadcast_end());
		return animation;
	}
}
```

#### repositoryの修正

Mapperを利用してmodelをentityに変換したら、JPAのsaveメソッドを使ってデータベースにレコードを登録します。

```java:AnimationRepositoryImpl.java
package com.volkruss.infrastructure.repository;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.volkruss.domain.entity.AnimationEntity;
import com.volkruss.domain.entity.AnimationRepository;
import com.volkruss.domain.mapper.AnimationMapper;
import com.volkruss.domain.model.Animation;

@Repository
public class AnimationRepositoryImpl implements AnimationRepository {

	@Autowired
	private AnimationJpaRepository animationJpaRepository;
	
	@Autowired
	private AnimationMapper animationMapper;
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<Animation> getAll() {
		List<AnimationEntity> lists = animationJpaRepository.findAll();
		return lists.stream().map(animationMapper::toAnimation).collect(Collectors.toList());
	}
	
	//　追加
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void insert(Animation animation) {
		AnimationEntity entity = animationMapper.toAnimationEntity(animation);
		animationJpaRepository.save(entity);
	}
}
```


#### Mapperの修正

modelをentityに変換します。
idはシーケンスを利用しているので勝手に連番が付与されます。

```java:AnimationMapperImpl.java
package com.volkruss.domain.mapper.impl;

import java.util.Objects;

import org.springframework.stereotype.Component;

import com.volkruss.domain.entity.AnimationEntity;
import com.volkruss.domain.mapper.AnimationMapper;
import com.volkruss.domain.model.Animation;

@Component
public class AnimationMapperImpl implements AnimationMapper{

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Animation toAnimation(AnimationEntity entity) {
		Animation animation = new Animation();
		animation.setTitle(entity.getTitle());
		animation.setBroadcast_start(entity.getBroadcast_start());
		animation.setBroadcast_end(entity.getBroadcast_end());
		return animation;
	}
	
	//　追加
	/**
	 * {@inheritDoc}
	 */
	@Override
	public AnimationEntity toAnimationEntity(Animation animation) {
		AnimationEntity entity = new AnimationEntity();
		if(Objects.nonNull(animation.getId())) {
			entity.setId(animation.getId());
		}		
		entity.setTitle(animation.getTitle());
		entity.setBroadcast_start(animation.getBroadcast_start());
		entity.setBroadcast_end(animation.getBroadcast_end());
		return entity;
	}
}
```

### 確認

登録ページ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/a622eb07-41d3-e144-a7dc-e8fd0aed834f.png)


登録後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/740759a5-b976-5355-863d-6d4d2699fc40.png)


###　終わりに

取得と登録のみですができました。
本当なら妥当性確認などの処理も入ってきます。