【Spring Boot入門】#8 削除機能を作成する

## はじめに
自身の知識のアウトプットも兼ねて、新人研修用に作成した記事となります。Spring Bootを学び始めた方を対象とした内容になっています。

更新機能の作成については、前回の記事を参照ください。

https://qiita.com/ioaio/items/1cef44733731a287b1dc

## 概要
企業情報一覧画面の「削除」リンクを押下した時に、特定の企業に関する情報を削除できるようにします。また、削除結果（成功 or エラー）が企業一覧画面へ表示されるようにします。

#### 完成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/46bd6efd-4a7b-f9a3-d6ca-b2b909400601.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/f7fe2571-5b9b-1412-959b-c17c1570719b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/57c12049-4f2c-16bb-b5ad-f07b009c19a3.png)

## パッケージ構成
青枠で囲ったクラス、及びHTMLファイルを編集していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/e4fd0309-78d8-eaa0-a6f2-31e8a13e85c7.png)

## Serviceクラスの修正
指定された企業IDに基づいてデータベースから企業情報を削除する処理を作成します。

`配置先：src > main > java > com > example > demo > service > CompanyService.java`

```java:CompanyService.java
@Service
public class CompanyService {

    // 企業情報の削除処理
	@Transactional
	public void deleteCompany(Long companyId) {
		repository.deleteById(companyId);
	}
}
```
#### deleteById(key)
`deleteById`メソッドは、Spring Data JPA が提供する標準の削除メソッドです。ここでは、`repository.deleteById(companyId)` により、引数として受け取った `companyId` をキーとして企業データをデータベースから削除します。

:::note warn
今回は研修のため、データベースから企業情報を**物理削除**していますが、基本的には削除するときは、削除フラグを立てるなどして**論理削除**することが多いです。
:::

## Controllerクラスの修正
企業情報の削除処理を行うためのコントローラメソッドを作成します。

`配置先：src > main > java > com > example > demo > controller > CompanyController.java`

```java:CompanyController.java
@Controller
public class CompanyController {

     // 企業情報の削除処理
	@GetMapping("company/delete/{id}")
	public String deleteCompany(@PathVariable Long id, RedirectAttributes redirectAttributes) {
	    try {
	        companyService.deleteCompany(id);
	        redirectAttributes.addFlashAttribute("successMessage", "企業情報が正常に削除されました。");
	    } catch (EmptyResultDataAccessException e) {
	        redirectAttributes.addFlashAttribute("errorMessage", "指定された企業IDが見つかりませんでした。");
	    } catch (Exception e) {
	        redirectAttributes.addFlashAttribute("errorMessage", "企業情報の削除に失敗しました。");
	    }
	    return "redirect:/company/lists";
	}
}
```
#### @￰PathVariable アノテーション
`@PathVariable` により、URLの `{id}` 部分が `id` パラメータとして取得されます。

`@RequestParam` はクエリパラメータに対して使用するものですが、ここではURLパスの一部としてIDが渡されるため、`@PathVariable` を使用するのが適切です。

#### RedirectAttributes
`RedirectAttributes`を使用して、削除が成功したか、エラーが発生したかに応じてメッセージを設定し、リダイレクト先のページ（この場合は一覧画面）にメッセージを渡します。

#### 例外処理
`EmptyResultDataAccessException`：削除対象の企業が見つからない場合に発生する例外で、エラーメッセージを設定します。

`その他のException`：予期しないエラーが発生した場合に備えて、一般的なエラーメッセージを設定します。

#### フラッシュメッセージの設定（`addFlashAttribute`）
削除が成功した場合やエラーが発生した場合に応じて、フラッシュメッセージとして `successMessage` や `errorMessage`を設定し、削除結果を一覧画面で確認できるようにしています。

## Viewの修正
index.htmlを修正していきます。
ここでは、削除ボタンと削除結果が確認できるようにフラッシュメッセージの表示部分を追加していきます。

`配置先：src > main > resources > templates > index.html`

#### 削除ボタン
削除ボタンを押したときに確認メッセージが表示されるようにすることで、誤操作を防ぐことができます。以下のように`onclick` イベントを使って削除リンクにアラートを追加します。

```html:index.html
<a th:href="@{/company/delete/{id}(id=${company.companyId})}"
			     onclick="return confirm('本当に削除しますか？');">削除</a>
```

削除ボタンをクリックした際に、本当に削除するか確認するアラートを表示するには、JavaScript の `confirm()` 関数を使います。`confirm()` は、ユーザーに「OK」または「キャンセル」の選択肢を提供し、OKをクリックすると `true`、キャンセルをクリックすると `false` を返します。

#### フラッシュメッセージの表示
削除処理の結果に応じたメッセージ（成功またはエラー）を一覧画面に表示するためのコードを追加します。

```html:index.html
    <!-- 削除処理が正常に完了した場合の成功メッセージを表示 -->
    <div th:if="${successMessage}">
        <p th:text="${successMessage}"></p>
    </div>
    <!-- 削除対象が見つからなかった場合やその他のエラーが発生した場合に、エラーメッセージを表示 -->
    <div th:if="${errorMessage}">
        <p th:text="${errorMessage}"></p>
    </div>
```
　
`th:if="${successMessage}"` は、`successMessage` が存在する場合に `<div>` 内の内容を表示する条件式です。`th:if="${successMessage}"`によって、`successMessage` の内容が `<p>` タグ内に表示されます。（ `errorMessage` に関しても同様のため、説明は割愛）

ここまでで、シンプルなCRUDアプリケーションの完成です。