質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Spring MVC

Spring MVCとは、Javaを用いてWebアプリケーションを開発できるフレームワーク。アーキテクチャにMVCを採用しており、画面遷移と入出力パラメータの受け渡しの基本的な機能の他、ユーザーの送信したパラメータに対する入力チェックなどさまざまな機能を持ちます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Thymeleaf

Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

0回答

642閲覧

テキストで勉強中、エラーが出ないので原因がどこかわからない。

Yudon

総合スコア0

Spring MVC

Spring MVCとは、Javaを用いてWebアプリケーションを開発できるフレームワーク。アーキテクチャにMVCを採用しており、画面遷移と入出力パラメータの受け渡しの基本的な機能の他、ユーザーの送信したパラメータに対する入力チェックなどさまざまな機能を持ちます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Thymeleaf

Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

1クリップ

投稿2022/11/28 03:40

編集2022/11/28 05:40

前提

Java、webアプリケーション初学者です。
周りに聞ける人がいないのでこちらで投稿させていただきました。
まだクラス間の流れを追っていくので精一杯の段階です。
「SpringFramework 超入門 やさしくわかるwebアプリ開発」樹下雅章氏 著
のテキストを読み進めながら、12章の最後まで実際にコードを入力し、動かしているのですが
狙った通りに動かないので原因を探っています。
理解が追い付いていないのはわかっているのですが、問題解決に向けてどこをみていけばよいのか等
アドバイスを頂けると大変助かります。

実現したいこと

  • Web上のボタンでデータの更新を行えるようしたい

発生している問題・エラーメッセージ

エラーメッセージはありません。
元のデータを更新したいが、実際には新しくデータが追加され、元あったデータが残ってしまいます。
以下、原因の部分がありそうなクラスファイルのソースを貼りました。

該当のソースコード

java

1package com.example.quiz.entity; 2 3import org.springframework.data.annotation.Id; 4 5import lombok.AllArgsConstructor; 6import lombok.Data; 7import lombok.NoArgsConstructor; 8 9/** quizテーブル用:Entity */ 10@Data 11@NoArgsConstructor 12@AllArgsConstructor 13public class Quiz { 14 /** 識別ID */ 15 @Id 16 private Integer id; 17 /** クイズの内容 */ 18 private String question; 19 /** クイズの解答 */ 20 private Boolean answer; 21 /** 作成者 */ 22 private String author; 23} 24package com.example.quiz.service; 25 26import java.util.Optional; 27 28import com.example.quiz.entity.Quiz; 29 30public interface QuizService { 31 /** クイズ情報を全件取得する */ 32 Iterable<Quiz> selectAll(); 33 /** クイズ情報を、idをキーに1件取得します */ 34 Optional<Quiz> selectOneById(Integer id); 35 /** クイズ情報をランダムに取得します */ 36 Optional<Quiz> selectOneRandomQuiz(); 37 /** クイズの正解/不正解を判定します */ 38 Boolean checkQuiz(Integer id,Boolean myAnswer); 39 /** クイズを登録します */ 40 void insertQuiz(Quiz quiz); 41 /** クイズ更新します */ 42 void updateQuiz(Quiz quiz); 43 /** クイズを削除します */ 44 void deleteQuizById(Integer id); 45} 46 47package com.example.quiz.controller; 48 49import java.util.Optional; 50 51import org.springframework.beans.factory.annotation.Autowired; 52import org.springframework.stereotype.Controller; 53import org.springframework.ui.Model; 54import org.springframework.validation.BindingResult; 55import org.springframework.validation.annotation.Validated; 56import org.springframework.web.bind.annotation.GetMapping; 57import org.springframework.web.bind.annotation.ModelAttribute; 58import org.springframework.web.bind.annotation.PathVariable; 59import org.springframework.web.bind.annotation.PostMapping; 60import org.springframework.web.bind.annotation.RequestMapping; 61import org.springframework.web.bind.annotation.RequestParam; 62import org.springframework.web.servlet.mvc.support.RedirectAttributes; 63 64import com.example.quiz.entity.Quiz; 65import com.example.quiz.form.QuizForm; 66import com.example.quiz.service.QuizService; 67 68/** Quizコントローラ */ 69@Controller 70@RequestMapping("/quiz") 71public class QuizController { 72 /** DI対象 */ 73 @Autowired 74 QuizService service; 75 /** 「from-backing bean」の初期化 */ 76 @ModelAttribute 77 public QuizForm setUpForm() { 78 QuizForm form = new QuizForm(); 79 // ラジオボタンのデフォルト値設定 80 form.setAnswer(true); 81 return form; 82 } 83 /** Quizの一覧を表示します */ 84 @GetMapping 85 public String showList(QuizForm quizForm,Model model) { 86 // 新規登録設定 87 quizForm.setNewQuiz(true); 88 // 掲示板の一覧を取得する 89 Iterable<Quiz> list = service.selectAll(); 90 // 表示用「Model」への格納 91 model.addAttribute("list",list); 92 model.addAttribute("title","登録用フォーム"); 93 return "crud"; 94 } 95 /** Quizデータを1件挿入 */ 96 @PostMapping("/insert") 97 public String insert(@Validated QuizForm quizForm,BindingResult bindingResult,Model model,RedirectAttributes redirectAttributes) { 98 // FormからEntityへの詰め替え 99 Quiz quiz = new Quiz(); 100 quiz.setQuestion(quizForm.getQuestion()); 101 quiz.setAnswer(quizForm.getAnswer()); 102 quiz.setAuthor(quizForm.getAuthor()); 103 // 入力チェック 104 if (!bindingResult.hasErrors()) { 105 service.insertQuiz(quiz); 106 redirectAttributes.addFlashAttribute("complete","登録が完了しました"); 107 return "redirect:/quiz"; 108 }else { 109 // エラーがある場合は、一覧表示処理を呼びます 110 return showList(quizForm,model); 111 } 112 } 113 /** Quizデータを1件取得し、フォーム内に表示する */ 114 @GetMapping("/{id}") 115 public String showUpdate(QuizForm quizForm,@PathVariable Integer id,Model model) { 116 //Quizを取得(Optionalでラップ) 117 Optional<Quiz> quizOpt = service.selectOneById(id); 118 //QuizFormへの詰め直し 119 Optional<QuizForm> quizFormOpt = quizOpt.map(t -> makeQuizForm(t)); 120 //QuizFormがnullでなければ中身を取り出す 121 if(quizFormOpt.isPresent()) { 122 quizForm = quizFormOpt.get(); 123 } 124 //更新用のModelを作成する 125 makeUpdateModel(quizForm,model); 126 return "crud"; 127 } 128 /** 更新用のModelを作成する */ 129 private void makeUpdateModel(QuizForm quizForm,Model model) { 130 model.addAttribute("id",quizForm.getId()); 131 quizForm.setNewQuiz(false); 132 model.addAttribute("quizForm",quizForm); 133 model.addAttribute("title","更新用フォーム"); 134 } 135 /** idをkeyにしてデータを更新する */ 136 @PostMapping("/update") 137 public String update( 138 @Validated QuizForm quizForm, 139 BindingResult result, 140 Model model, 141 RedirectAttributes redirectAttributes) { 142 //QuizFormからQuizに詰め直す 143 Quiz quiz = makeQuiz(quizForm); 144 // 入力チェック 145 if(!result.hasErrors()) { 146 //更新処理、フラッシュスコープの使用、リダイレクト(個々の編集ページ) 147 service.updateQuiz(quiz); 148 redirectAttributes.addFlashAttribute("complete","更新が完了しました"); 149 // 更新画面を表示する 150 return "redirect:/quiz/" + quiz.getId(); 151 }else { 152 // 更新用のModelを作成する 153 makeUpdateModel(quizForm,model); 154 return "crud"; 155 } 156 } 157 // ----------【以下はFormとDomainObjectの詰めなおし】---------- 158 /** QuizFormからQuizに詰め直して戻り値とし返します */ 159 private Quiz makeQuiz(QuizForm quizForm) { 160 Quiz quiz = new Quiz(); 161 quiz.setId(quizForm.getId()); 162 quiz.setQuestion(quizForm.getQuestion()); 163 quiz.setAnswer(quizForm.getAnswer()); 164 quiz.setAuthor(quizForm.getAuthor()); 165 return quiz; 166 } 167 /** QuizからQuizFormに詰め直して戻り値とし返します */ 168 private QuizForm makeQuizForm(Quiz quiz) { 169 QuizForm form = new QuizForm(); 170 form.setId(quiz.getId()); 171 form.setQuestion(quiz.getQuestion()); 172 form.setAnswer(quiz.getAnswer()); 173 form.setAuthor(quiz.getAuthor()); 174 form.setNewQuiz(false); 175 return form; 176 } 177crud.html 178<!DOCTYPE html> 179<html xmlns:th="http://www.thymeleaf.org"> 180<head> 181<meta charset="UTF-8"> 182<title>「〇×クイズ」アプリ:CRUD</title> 183</head> 184<body> 185 <h1>「〇×クイズ」アプリ:CRUD</h1> 186 <h3 th:text="${title}">タイトル</h3> 187 <!-- /* 登録・更新完了コメント*/ --> 188 <p th:if="${complete}" th:text="${complete}" style= "color:blue"></p> 189 <!--/* ▼▼▼ Form ▼▼▼ */--> 190 <form method="POST" 191 th:action="${quizForm.newQuiz}? @{/quiz/insert} : @{/quiz/update}" 192 th:object="${quizForm}"> 193 <label>クイズの内容:</label><br> 194 <textarea rows="5" cols="50" th:field="*{question}"></textarea> 195 <br> 196 <div th:if="${#fields.hasErrors('question')}" th:errors="*{question}" 197 style="color:red"></div> 198 <label>クイズの解答</label><br> 199 <input type="radio" value="true" th:field="*{answer}">「〇」 200 <input type="radio" value="false" th:field="*{answer}">「×」 201 <br> 202 <div th:if="${#fields.hasErrors('answer')}" th:errors="*{answer}" 203 style="color:red"></div> 204 <label>作成者:</label><br> 205 <input type="text" th:field="*{author}" /> 206 <br> 207 <div th:if="${#fields.hasErrors('author')}" th:errors="*{answer}" 208 style="color=red"></div> 209 <input th:if="${id}" type="hidden" th:field="${id}"> 210 <input type="submit" value="送信"> 211 </form> 212 <!--/* △△△ Form △△△*/--> 213 <br> 214 <!--/* ========== ここまで上部エリア ========== */--> 215 <hr> 216 <!--/* ========== ここから下部エリア ========== */--> 217 <!--/* ▼▼▼ 新規登録時のみ表示 ▼▼▼ */--> 218 <div th:if="${quizForm.newQuiz}" style="margin: 10px"> 219 <h3>登録クイズ一覧:<a th:href="@{/quiz/play}">プレイ</a><br></h3> 220 <!--/* 削除完了コメント */--> 221 <p th:if="${delcomplete}" th:text="${delcomplete}" style="color:blue"></p> 222 <p th:if="${msg}" th:text="${msg}" style="color:red"></p> 223 <!--/* ▼▼▼ クイズ情報が1件でもあれば表示 ▼▼▼ */--> 224 <table border="1" th:unless="${#lists.isEmpty(list)}" 225 style="table-layout: fixed;"> 226 <tr> 227 <th>ID</th> 228 <th>内容</th> 229 <th>解答</th> 230 <th>作成者</th> 231 <th>編集</th> 232 <th>削除</th> 233 </tr> 234 <tr th:each="obj : ${list}" align="center"> 235 <td th:text="${obj.id}"></td> 236 <td th:text="${obj.question}" align="left"></td> 237 <td th:text="${obj.answer} == true?'〇':'×'"></td> 238 <td th:text="${obj.author}"></td> 239 <!--/* 編集ボタン */--> 240 <td> 241 <form method="GET" th:action="@{/quiz/{id}(id=${obj.id})}"> 242 <input type="submit" value="編集"> 243 </form> 244 </td> 245 <!--/* 削除ボタン */--> 246 <td> 247 <form method="POST" th:action="@{/quiz/delete}"> 248 <input type="hidden" name="id" th:value="${obj.id}"> 249 <input type="submit" value="削除"> 250 </form> 251 </td> 252 </tr> 253 </table> 254 <!--/* △△△ クイズ情報が1件でもあれば表示 △△△ */--> 255 <!--/* ▼▼▼ クイズ情報が1件もない場合表示 ▼▼▼ */--> 256 <p th:if="${#lists.isEmpty(list)}">登録されているクイズはありません。</p> 257 <!--/* △△△ クイズ情報が1件もない場合表示 △△△ */--> 258 </div> 259 <!--/* △△△ 新規登録字のみ表示 △△△ */--> 260 <!--/* ▼▼▼ 新規登録時でない時に表示 ▼▼▼ */--> 261 <p th:unless="${quizForm.newQuiz}"> 262 <a href="#" th:href="@{/quiz}">CRUD画面へ戻る</a> 263 </p> 264 <!--/* △△△ 新規登録時でない時に表示 △△△ */--> 265</body> 266</html>

試したこと

コードのスペルチェック

補足情報(FW/ツールのバージョンなど)

Spring Boot 2.7.5
Eclipse 4.24.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2022/11/28 04:49 編集

エラーメッセージ等、パソコンの画面に表示されているもの以外は、コードのマークダウン(```の囲み)の外に書いてください。 また、件名は質問内容が分かるようにしてください。 「テキストで勉強中、エラーが出ないので原因がどこかわからない。」では『元のデータを更新したいが、実際には新しくデータが追加され、元あったデータが残ってしまいます』ということが分かりません。 そもそも update は呼ばれているでしょうか。
syoshinsya-

2022/11/28 04:52

Quizのデータを管理しているのはDBで、それにアクセスしているのはQuizServiceクラスだと思います。 QuizServiceクラスの中身を見たいです
syoshinsya-

2022/11/28 04:56

確認すべき点 jimbeさんが >そもそも update は呼ばれているでしょうか。 といっているように、web上のフォームからのリクエストを確認する必要があります。 HTMLファイルも貼ってほしいです。 >QuizServiceクラスの中身を見たいです QuizServiceクラスの中にあると思われるSQL(かそれに準ずるもの)が間違っているとinsertされてしまいます。 QuizServiceクラスも貼ってほしいです
m.ts10806

2022/11/28 05:05

他者がコピペで再現できるよう、配慮願います。 問題がどこにあるか分からない場合、必ず自身でデバッグすべきですが、 デバッグによってどこまで追えているかという情報と共に、 全体の流れが分かるようなコードを提示してください コントローラ(しかも無駄に機能持たせすぎのファット状態)だけ提示されても分かることはほぼないです。
Yudon

2022/12/02 05:34 編集

投稿を載せてから数分でコメントをたくさんいただいたことに驚いていると同時に感謝しております。 投稿のルール等を理解していなかったため、見づらくてすみません。 私の学習速度だとコメントでおっしゃられていることを理解した上で適切な返事をするのに時間がかかりそうです。
jimbe

2022/11/28 05:51 編集

動作しているプログラムがどう動いているかを確認するのに一番簡単なのは、あちこちに System.out.println("A") のようなマーカーを入れて動かし、どれがどの順に出力されたか、それが考えていたように出力されたのかを見ることです。 (Web アプリなら println では無くログ出力でしょうか。) 刑事ドラマで人や車が何時何処に行ったかを各地の監視カメラ映像で探すようなものですね。 "A",”B",”C" を入れて A→B→C と出力される(=実行される)はずなのに A→C だったら、 B に行っていない…ということです。 編集ありがとうございます。
Yudon

2022/12/02 05:38

>> jimbeさん コンソールにメッセージを表示させるやり方をしてみたら理解が深まりました。 原因はまだわかっていないのですが、この方法でやっていけばいずれ答えにたどり着けそうです。 時間がかかりそうなのでこちらのスレッドでの質問はいったん終わりにさせていただきます。 もっと疑問点をまとめてから投稿すべきでした、出直してきます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問