JPAという便利なものがあるらしいVer2

## 前回まで
- JPA(Java Persistence API)を利用して用意されている複数のSelect文を実行した
- 全件検索→findAll()メソッド
- 主キー検索→getOne()メソッド
- findBy[検索条件]→findByに続くフィールド名、キーワードに応じた条件検索を実行

## 本日行うこと
- JPAを用いて登録、更新、削除処理を行う
- レコードを登録、または更新する→save()メソッド
- 指定された主キーに該当するレコードを削除する→deleteById()メソッド

## 登録処理

①新規登録画面へ遷移、値の入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/22e24f06-e2c5-3d4e-5069-3fcfa61f9bda.png)

②登録ボタン押下後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/97fd83e7-028d-f759-0924-e5ff299e3b28.png)

③確認用(全検索処理実行)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/a04bb747-1da1-402c-88da-568a83c82732.png)

※従業員番号：10、従業員名：test、部署番号：1のデータが新規登録されている。

## 更新処理

①更新内容入力画面へ遷移時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/001c0684-bc39-a2a9-b459-89bf9f3ce97d.png)

②入力内容を変更(従業員名をtest2に変更)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/ba8b7444-870b-f0ce-8925-43660d7c1def.png)

③更新ボタンを押下後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/52db3c6e-930e-0053-189c-7c060c1004ed.png)

④確認用(全検索処理実行)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/ebd3698f-7833-e8c8-ae91-65a4fb48870b.png)

※従業員番号：10のデータにおいて従業員名がtest2に更新されている。

## 更新処理

①削除画面に遷移、値の入力(従業員番号10のデータを削除する)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/c150890a-c66d-04a0-9541-f52c4bfe1f23.png)

②削除ボタン押下後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715093/c59402ce-9bf9-4e97-29aa-cca0336dfd6b.png)

※従業員番号：10のデータが削除されている。

## Controller
```java
package jp.co.ttt.employee.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import jp.co.ttt.employee.entity.Employee;
import jp.co.ttt.employee.form.EmployeeForm;
import jp.co.ttt.employee.repository.EmployeeRepository;

@Controller
public class EmployeeController {

	@Autowired
	EmployeeRepository repository;

	// 全件検索
	@RequestMapping(path = "/findAll")
	public String showemployeeList(Model model) {

		model.addAttribute("employees", repository.findAll());
		return "employee/employee_list";
	}

	// 主キー(従業員番号)検索
	@RequestMapping(path = "/getOne/{id}")
	public String showEmployee(@PathVariable int id, Model model) {

		model.addAttribute("employees", repository.getOne(id));
		return "employee/employee_list";
	}

	// 部署番号検索を行う
	@RequestMapping(path = "/findByDeptNo/{deptNo}")
	public String showEmpoloyeeListByDeptNo(@PathVariable int deptNo, Model model) {

		System.out.println(repository.findByDeptNo(deptNo));
		model.addAttribute("employees", repository.findByDeptNo(deptNo));
		return "employee/employee_list";
	}

	// 従業員名＆部署番号検索を行う
	@RequestMapping(path = "/findByNameAndDeptNo/{name}/{deptNo}")
	public String showEmpoloyeeListByNameAndDeptNo(@PathVariable String name, @PathVariable int deptNo,
			Model model) {

		model.addAttribute("employees", repository.findByNameAndDeptNo(name, deptNo));
		return "employee/employee_list";
	}

	// 従業員名部分検索を行う
	@RequestMapping(path = "/findByNameLike/{name}")
	public String showEmployeeListNameLike(@PathVariable String name, Model model) {

		model.addAttribute("employees", repository.findByNameLike("%" + name + "%"));
		return "employee/employee_list";
	}

	// 新規登録画面に遷移する
	@RequestMapping(path = "/create/input")
	public String createInput() {

		return "employee/create_input";
	}

	// 従業員を登録する
	@RequestMapping(path = "/create/complete", method = RequestMethod.POST)
	public String createComplete(EmployeeForm form) {

		Employee employee = new Employee();
		employee.setId(form.getId());
		employee.setName(form.getName());
		employee.setDeptNo(form.getDeptNo());
		repository.save(employee);

		return "redirect:/getOne/" + employee.getId();
	}

	// 更新内容入力画面に遷移する
	@RequestMapping(path = "/update/input/{id}")
	public String updateInput(@PathVariable int id, Model model) {

		model.addAttribute("employee", repository.getOne(id));
		return "employee/update_input";
	}

	// 従業員情報を更新する
	@RequestMapping(path = "/update/complete/{id}", method = RequestMethod.POST)
	public String updateComplete(@PathVariable int id, EmployeeForm form) {

		Employee employee = repository.getOne(id);
		employee.setId(form.getId());
		employee.setName(form.getName());
		employee.setDeptNo(form.getDeptNo());
		repository.save(employee);
		return "redirect:/getOne/" + employee.getId();
	}

	// 削除画面に遷移する
	@RequestMapping(path = "/delete/input")
	public String deleteInput() {

		return "employee/delete_input";
	}

	// 従業員を削除する
	@RequestMapping(path = "/delete/complete", method = RequestMethod.POST)
	public String deleteComplete(EmployeeForm form) {

		repository.deleteById(form.getId());
		return "redirect:/findAll";
	}

}

```

- 検索処理は前回と同様
- 登録、更新、削除処理において、入力画面遷移(新規登録入力画面など)と実行後の遷移の2パターンずつそれぞれメソッドを実装

## Form
```java
package jp.co.ttt.employee.form;

import lombok.Data;

@Data
public class EmployeeForm {

	private Integer id;

	private String name;

	private Integer deptNo;
}

```
- 画面の入力情報をコントローラーに渡すためのクラス
- 従業員番号、従業員名、部署番号のフィールドとgetter, setter(Lombokで対応)

## HTML(登録入力画面)
```html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div>商品の新規登録</div>
	<form method="post" th:action="@{/create/complete}">
		従業員ID：<input type="number" name="id">
		従業員名：<input type="text" name="name">
		部署番号：<input type="number" name="deptNo">
		<input type="submit" value="登録する">
	</form>
</body>
</html>
```

- 新規登録情報を入力する画面
- 登録ボタン押下後は、登録した1件のデータを再度表示

## HTML(更新入力画面)
```html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div>商品の編集</div>
	<form method="post" th:action="@{/update/complete/} + ${employee.id}">
		従業員ID：<input type="number" name="id" th:value="${employee.id}">
		従業員名：<input type="text" name="name" th:value="${employee.name}">
		部署番号：<input type="number" name="deptNo" th:value="${employee.deptNo}">
		<input type="submit" value="更新する">
	</form>
</body>
</html>
```

- 更新情報を入力する画面
- 画面遷移時に既に登録されている元のデータ入力されている状態で遷移
- データを更新、更新ボタンを押下すると、更新された状態の1件のデータを表示

## HTML(削除入力画面)
```html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div>商品の削除</div>
	<form method="post" th:action="@{/delete/complete}">
		従業員番号：<input type="text" name="id">
		<input type="submit" value="削除する">
	</form>
</body>
</html>
```

- 削除したいデータを削除する画面
- 削除したい従業員番号を入力し、削除ボタンを押下するとデータが削除され全件検索画面を表示

## ソースコード
https://github.com/takaaki18/employee

## ふりかえり
- 登録処理と更新処理のメソッドが同じなのが驚きだった。(てっきり別のメソッドだと感じていたので…)
- JPAを用いると最低限のCRUD処理を実装する程度なら問題ない印象を受けた