2
0

More than 1 year has passed since last update.

Spring BootのWebアプリケーションの応用③〜注文フォームの更新と削除~

Last updated at Posted at 2023-08-20

前回の記事は、注文フォームにトランザクションと二重サブミット対策とバリデーションを追加をしました。

今回は、注文フォームの更新と削除の機能を追加していきましょう。

ファイル構成


.
├── .gradle
├── .idea
├── build
├── gradle
└── src
     ├── main
     |      ├── java
     |      |      └── com
     |      |           └── example
     |      |                 └── practice 
     |      |                          PracticeApplication.java
     |      |                          ├── web 
     |      |                          |    ├── order
     |      |                          |    |    ├── OrderForm.java
     |      |                          |    |      └── OrderController.java
     |      |                          |    |                
     |      |                          |    └── IndexController.java
     |      |                          └── domain
     |      |                                 └── order 
     |      |                                       └── OrderEntity.java
     |      |                                       └── OrderService.java
     |      |                                       └── OrderRepository.java
     |      |                               
     |      └── resources
     |              ├── static
     |              ├── templates
     |              |        └── order
     |              |                           
     ├──delete_confirmation.html
     |              |                  ├── detail.html 
     |              |                  ├── form.html 
     |              |                  └── list.html
     |              └── index.html
     |              schema.sql
     |              data.sql 
     |                    application.properties
     └── test
.gitignore
build.gradle
gradlew.bat
HELP.md
settings.gradle

今回作成したい完成形を見ていきましょう。

注文番号をクリックすると、注文リストの詳細が表示されます。

スクリーンショット 2023-08-21 7.42.05.png

注文リストの詳細では、既存のデータを修正または削除できるようにします。

スクリーンショット 2023-08-21 7.42.11.png

削除ボタンをクリックすると、確認画面が表示され、削除ボタンをクリックすると、削除されます。

スクリーンショット 2023-08-21 7.42.16.png

Modelの作成

まずは、OrderRepositoryから追加していきます。

最初に、注文番号をクリックすると、注文リストの詳細が表示されるように、特定の注文番号のIDを取得します。

@Select("select * from ORDERS where order_id = #{orderId}")
OrderEntity findById(long orderId);

@Update アノテーションは、指定された SQLクエリを使用してデータベース内のデータを更新するためのメソッドを定義する際に使用し、修正する機能ができます。

@Delete アノテーションは、データベースからデータを削除するためのメソッドを定義する際に使用し、削除する機能ができます。

OrderRepository
package com.example.practice.domain.order;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Delete;
import java.util.List;
import com.example.practice.web.order.OrderForm;
import org.apache.ibatis.annotations.Options;

@Mapper
public interface OrderRepository {
    @Select("select * from orders")
    List<OrderEntity> findAll();
    @Insert("insert into ORDERS(order_id,order_date,company_no,company_name,item_no,item,quantity,unit_price,price) values (#{orderId}, #{orderDate}, #{companyNo}, #{companyName}, #{itemNo}, #{item}, #{quantity}, #{unitPrice}, #{price})")
    void insert(OrderForm orderForm);
    @Select("SELECT MAX(CAST(order_id AS SIGNED)) FROM ORDERS")
    Integer findMaxOrderId();
    @Select("select * from ORDERS where order_id = #{orderId}")
    OrderEntity findById(long orderId);
    @Update("update ORDERS set order_date = #{orderDate}, company_no = #{companyNo}, company_name = #{companyName}, item_no = #{itemNo}, item = #{item}, quantity = #{quantity}, unit_price = #{unitPrice}, price = #{price} where order_id = #{orderId}")
    void update(OrderForm orderForm);
    @Delete("delete from ORDERS where order_id = #{orderId}")
    void delete(long orderId);
}

次に、OrderRepositoryで追加したコードのロジックを追加します。

OrderService
package com.example.practice.domain.order;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.example.practice.web.order.OrderForm;
import java.util.List;
import org.springframework.ui.Model;
import org.springframework.transaction.annotation.Transactional;
import java.lang.IllegalAccessException;

@Service
@RequiredArgsConstructor
public class OrderService {
    private final OrderRepository repository;
    @Transactional(readOnly = true)
    public List<OrderEntity> findAll() {
        return repository.findAll();
    }
    @Transactional
    public void create(OrderForm form, Model model) {
        int nextOrderId = getNextOrderId(); // 事前にorderIdを取得するメソッド
        form.setOrderId(nextOrderId); // OrderFormに次のorderIdを設定
        repository.insert(form); // OrderFormをDBに挿入
    }
    // 最大orderId + 1を計算して返すメソッド
    public int getNextOrderId() {
        Integer maxOrderId = repository.findMaxOrderId();
        if (maxOrderId == null) {
            return 1; // 最初の場合、1を返す
        }
        int nextId = maxOrderId + 1;
        System.out.println(nextId);
        return nextId;
    }
    //指定された orderId を使用して、データベースから該当する注文情報を取得するメソッド
    public OrderEntity findById(long orderId) {
        return repository.findById(orderId);
    }
    //渡された OrderForm オブジェクトの情報を使用して、データベース内の注文情報を更新するためメソッド
    @Transactional
    public void update(OrderForm form, Model model) {
        repository.update(form);
    }
    //指定された orderId を使用して、データベース内の注文情報を削除するためメソッド
    @Transactional
    public void delete(long orderId) {
        repository.delete(orderId);
    }
}

Controllerの作成

注文情報を詳細表示、更新、削除するためのメソッドを作成します。

以下がその内容のコードです。

OrderController
package com.example.practice.web.order;

import com.example.practice.domain.order.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import java.time.LocalDate;
@Controller
@RequestMapping("/orders")
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;
    @GetMapping
    public String showList(Model model) {
        //orderServiceクラスのfindAllメソッドで取得されたオーダーリストを、orderListでビューに渡す
        model.addAttribute("orderList", orderService.findAll());
        // "order/list"という名前のThymeleafビューを表示する
        return "order/list";
    }
    @GetMapping("/form")
    public String showForm(@ModelAttribute OrderForm form, Model model) {
        int nextOrderId = orderService.getNextOrderId();
        form.setOrderId(nextOrderId);
        form.setOrderDate(LocalDate.now());
        model.addAttribute("nextOrderId", nextOrderId);
        return "order/form";
    }
    @PostMapping
    public String create(@Validated OrderForm form, BindingResult bindingResult, Model model) {
        if (bindingResult.hasErrors()) {
            return showForm(form, model);
        }
        orderService.create(form, model);
        return "redirect:/orders";
    }
    @GetMapping("/{orderId}")
    public String showDetail(@PathVariable("orderId") long orderId, Model model) {
        // 特定の注文の詳細を表示するためのメソッド
        // URLパラメータからorderIdを受け取り、その注文の詳細情報をデータベースから取得してモデルに追加
        model.addAttribute("order", orderService.findById(orderId));
        return "order/detail"; // 注文の詳細を表示するためのビューにリダイレクト
    }

    @PostMapping("/update")
    public String update(@Validated OrderForm form, BindingResult bindingResult, Model model) {
        // 注文情報を更新するためのメソッド
        // フォームデータを受け取り、バリデーションエラーがある場合はフォームを再表示
        if (bindingResult.hasErrors()) {
            return showForm(form, model); // 更新フォームを表示するためのメソッドを呼び出し
        }
        System.out.println("OrderForm:" + form); // フォームデータをコンソールに出力(デバッグ用)
        return "redirect:/orders"; // オーダー一覧画面にリダイレクト
    }

    @GetMapping("/delete/{orderId}")
    public String showDeleteConfirmation(@PathVariable("orderId") long orderId, Model model) {
        // 注文の削除確認画面を表示するためのメソッド
        // URLパラメータからorderIdを受け取り、削除対象の注文の情報をデータベースから取得してモデルに追加
        model.addAttribute("order", orderService.findById(orderId));
        return "order/delete_confirmation"; // 削除確認画面を表示するためのビューにリダイレクト
    }

    @PostMapping("/delete/{orderId}")
    public String deleteOrder(@PathVariable("orderId") long orderId) {
        // 注文を削除するためのメソッド
        orderService.delete(orderId); // 指定されたorderIdに対応する注文をデータベースから削除
        return "redirect:/orders"; // オーダー一覧画面にリダイレクト
    }
}

Viewの作成

次に、詳細画面と削除詳細画面のViewを作成します。

list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>注文リスト</title>
</head>
<body>
<h1>注文リスト</h1>
<a href="../index.html" th:href="@{/}">トップページ</a>
<a href="./form.html" th:href="@{/orders/form}">作成</a>

<table>
    <tr>
        <th>注文番号</th>
        <th>納入日付</th>
        <th>会社番号</th>
        <th>会社名</th>
        <th>品物番号</th>
        <th>品物</th>
        <th>数量</th>
        <th>単価</th>
        <th>金額</th>
    </tr>
    <!-- orderList の内容をループして表示 -->
    <tr th:each="order : ${orderList}">
        <td>
            <a href="./detail.html" th:href="@{/orders/{orderId}(orderId=${order.orderId})}" th:text="${order.orderId}">
                (orderId)
            </a>
        </td>
        <td th:text="${order.orderDate}"></td>
        <td th:text="${order.companyNo}"></td>
        <td th:text="${order.companyName}"></td>
        <td th:text="${order.itemNo}"></td>
        <td th:text="${order.item}"></td>
        <td th:text="${order.quantity}"></td>
        <td th:text="${order.unitPrice}"></td>
        <td th:text="${order.price}"></td>
    </tr>
</table>
</body>
</html>
detail.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>注文リストフォーム</title>
</head>
<body>
<h1>注文リスト詳細</h1>
<form th:object="${order}" th:action="@{/orders/update}" method="post">
    <div>
        <input type="hidden" th:field="*{orderId}"> <!-- orderId を hidden フィールドとして追加 -->
        <label>注文番号</label>
        <span th:text="${order.orderId}"></span>
    </div>
    <div>
        <label for="orderDate">納入日付</label>
        <input type="date" id="orderDate" th:field="*{orderDate}">
        <p th:if="${#fields.hasErrors('orderDate')}" th:errors="*{orderDate}">(error)</p>
    </div>
    <div>
        <label for="companyNo">会社番号</label>
        <input type="number" id="companyNo" th:field="*{companyNo}">
        <p th:if="${#fields.hasErrors('companyNo')}" th:errors="*{companyNo}">(error)</p>
    </div>
    <div>
        <label for="companyName">会社名</label>
        <input type="text" id="companyName" th:field="*{companyName}">
        <p th:if="${#fields.hasErrors('companyName')}" th:errors="*{companyName}">(error)</p>
    </div>
    <div>
        <label for="itemNo">品物番号</label>
        <input type="number" id="itemNo" th:field="*{itemNo}">
        <p th:if="${#fields.hasErrors('itemNo')}" th:errors="*{itemNo}">(error)</p>
    </div>
    <div>
        <label for="item">品物</label>
        <input type="text" id="item" th:field="*{item}">
        <p th:if="${#fields.hasErrors('item')}" th:errors="*{item}">(error)</p>
    </div>
    <div>
        <label for="quantity">数量</label>
        <input type="number" id="quantity" th:field="*{quantity}">
        <p th:if="${#fields.hasErrors('quantity')}" th:errors="*{quantity}">(error)</p>
    </div>
    <div>
        <label for="unitPrice">単価</label>
        <input type="number" id="unitPrice" th:field="*{unitPrice}">
        <p th:if="${#fields.hasErrors('unitPrice')}" th:errors="*{unitPrice}">(error)</p>
    </div>
    <div>
        <label for="price">金額</label>
        <input type="number" id="price" th:field="*{price}">
        <p th:if="${#fields.hasErrors('price')}" th:errors="*{price}">(error)</p>
    </div>
    <button type="submit">更新</button>
    <a th:href="@{/orders/delete/{orderId}(orderId=${order.orderId})}">削除</a>
    <a href="./order/list.html" th:href="@{/orders}">取消</a>
</form>
</body>
</html>
delete_confirm
<!-- delete_confirmation.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>注文リスト削除確認</title>
</head>
<body>
<h1>注文リスト削除確認</h1>
<p>以下の注文を削除しますか?</p>
<p>注文番号: <span th:text="${order.orderId}"></span></p>
<p>納入日付: <span th:text="${order.orderDate}"></span></p>
<p>会社番号: <span th:text="${order.companyNo}"></span></p>
<p>品物番号: <span th:text="${order.itemNo}"></span></p>
<p>品物: <span th:text="${order.item}"></span></p>
<p>数量: <span th:text="${order.quantity}"></span></p>
<p>単価: <span th:text="${order.unitPrice}"></span></p>
<p>金額: <span th:text="${order.price}"></span></p>
<!-- 削除処理を実行するURLを指定 -->
<form th:action="@{/orders/delete/{orderId}(orderId=${order.orderId})}" method="post">
  <button type="submit">削除</button>
  <a th:href="@{/orders}">キャンセル</a>
</form>
</body>
</html>
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0