如何在Thymeleaf页面根据用户选择输出H2数据库指定行?排查500错误
问题:H2数据库查询与页面渲染500错误排查及功能实现
我有一个预填充数据的H2数据库,希望通过页面上的select元素选择后输出指定行数据,但访问characterCreator页面时出现HTML 500错误。
现有配置与代码
application.properties配置
spring.h2.console.enabled=true spring.datasource.url=jdbc:h2:mem:348dae81-3b35-422e-8aa6-eb69a6163544 spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=
characterCreator.html代码
<div style="margin:auto; text-align: center;"> <form action="/characterCreator" method="get"> <select style="align-self: center;" th:field="*{id}"> <option th:each="race : ${RACE}" th:value="${race.ID}" th:text="${race.RACE_NAME}">Select Race </option> </select> <br><br> <input type="submit" value="Select"> </form> </div>
RaceController.java代码
import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/characterCreator") public class RaceController { private final RaceRepository raceRepository; public RaceController(RaceRepository raceRepository) { this.raceRepository = raceRepository; } @Autowired private JdbcTemplate jdbcTemplate; @GetMapping("/{id}") public String getRace(@PathVariable int id) { String query = "SELECT * FROM RACE WHERE ID = ?"; List<Map<String, Object>> rows = jdbcTemplate.queryForList(query, id); return rows.get(0).get("ID").toString(); } }
HomeController.java代码
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class HomeController { @GetMapping({"/", "/home"}) public String getHome() { return "home"; } @GetMapping("/generalLore") public String getGeneralLore() { return "generalLore"; } @GetMapping("/characterCreator") public String getCharacterCreator() { return "characterCreator"; } @GetMapping("/exampleCharacter") public String getExampleCharacter() { return "exampleCharacter"; } }
数据库表结构
H2数据库中RACE表包含ID、RACE_NAME等字段,已验证查询语句在H2控制台可正常返回对应结果。
错误原因与解决方案
1. 页面渲染500错误的核心原因
HomeController返回characterCreator页面时,未向Thymeleaf模板传递RACE列表数据,导致模板中${RACE}变量为空,触发渲染异常。
修复方法:修改HomeController
注入JdbcTemplate,查询所有种族数据并添加到模型中:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.ui.Model; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; import java.util.Map; @Controller public class HomeController { @Autowired private JdbcTemplate jdbcTemplate; @GetMapping({"/", "/home"}) public String getHome() { return "home"; } @GetMapping("/generalLore") public String getGeneralLore() { return "generalLore"; } @GetMapping("/characterCreator") public String getCharacterCreator(Model model) { // 查询所有种族数据传递给模板 List<Map<String, Object>> races = jdbcTemplate.queryForList("SELECT * FROM RACE"); model.addAttribute("RACE", races); return "characterCreator"; } @GetMapping("/exampleCharacter") public String getExampleCharacter() { return "exampleCharacter"; } }
2. 表单提交与接口路径不匹配问题
当前表单提交的URL是/characterCreator?id=xxx(GET请求带参数),但RaceController的接口是/characterCreator/{id}(路径变量),两者不匹配,无法正确接收参数。
修复方法二选一:
方案A:调整RaceController接口接收请求参数
@RestController @RequestMapping("/characterCreator") public class RaceController { @Autowired private JdbcTemplate jdbcTemplate; // 删除未使用的RaceRepository相关代码,避免不必要的依赖问题 // private final RaceRepository raceRepository; // public RaceController(RaceRepository raceRepository) { // this.raceRepository = raceRepository; // } @GetMapping public String getRace(@RequestParam int id) { String query = "SELECT * FROM RACE WHERE ID = ?"; List<Map<String, Object>> rows = jdbcTemplate.queryForList(query, id); // 处理查询结果为空的情况,避免空指针异常 if (rows.isEmpty()) { return "Race not found"; } return rows.get(0).get("RACE_NAME").toString(); // 可根据需求返回字段 } }
方案B:调整表单提交路径(需配合JS动态修改,适合REST风格场景)
修改表单的action为动态路径,或者通过JavaScript监听select选择事件,修改表单action:
<form id="raceForm" method="get"> <select style="align-self: center;" id="raceSelect" th:field="*{id}"> <option th:each="race : ${RACE}" th:value="${race.ID}" th:text="${race.RACE_NAME}">Select Race </option> </select> <br><br> <input type="submit" value="Select"> </form> <script> document.getElementById('raceSelect').addEventListener('change', function() { const raceId = this.value; document.getElementById('raceForm').action = `/characterCreator/${raceId}`; }); </script>
3. 其他潜在问题修复
- 删除
RaceController中未使用的RaceRepository依赖,避免因未正确定义该Repository导致的初始化错误; - 在查询数据库时添加空结果判断,防止
rows.get(0)抛出IndexOutOfBoundsException。
内容的提问来源于stack exchange,提问作者InferableSole6
相关产品推荐
相关产品推荐

