SpringBoot Web服务:如何用拆分后的请求参数查询并映射数据库结果
解决方案
步骤1:修正SQL语句并传递拆分后的参数
首先修正原SQL的语法错误(原语句中PERSON与where之间缺少空格,会导致SQL解析失败),然后将Controller拆分得到的first_name和last_name传递给服务层的查询方法。
步骤2:使用JdbcTemplate执行查询并映射到实体类
JdbcTemplate提供两种常用的结果映射方式,可根据你的实体类命名习惯选择:
情况1:实体类字段与数据库列名完全一致
假设你的Person实体类字段与数据库列名完全匹配:
public class Person { private String first_name; private String last_name; private String email; private String city; // 必须提供无参构造方法 public Person() {} // 全参构造方法(可选) public Person(String first_name, String last_name, String email, String city) { this.first_name = first_name; this.last_name = last_name; this.email = email; this.city = city; } // 所有字段的getter和setter方法(必须实现) public String getFirst_name() { return first_name; } public void setFirst_name(String first_name) { this.first_name = first_name; } public String getLast_name() { return last_name; } public void setLast_name(String last_name) { this.last_name = last_name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } }
服务层代码示例:
@Service public class PersonService { @Autowired private JdbcTemplate jdbcTemplate; public Person getPersonByName(String firstName, String lastName) { String sql = "SELECT first_name, last_name, email, city FROM PERSON WHERE first_name = ? AND last_name = ?"; try { // 使用BeanPropertyRowMapper自动映射到实体类 return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Person.class), firstName, lastName); } catch (EmptyResultDataAccessException e) { // 未查询到对应记录时返回null return null; } } }
情况2:实体类使用驼峰命名(符合Java规范)
如果实体类采用驼峰命名(如firstName对应数据库first_name),可自定义RowMapper手动映射:
实体类定义:
public class Person { private String firstName; private String lastName; private String email; private String city; public Person() {} // getter和setter方法 public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } }
自定义RowMapper:
public class PersonRowMapper implements RowMapper<Person> { @Override public Person mapRow(ResultSet rs, int rowNum) throws SQLException { Person person = new Person(); person.setFirstName(rs.getString("first_name")); person.setLastName(rs.getString("last_name")); person.setEmail(rs.getString("email")); person.setCity(rs.getString("city")); return person; } }
服务层调用自定义RowMapper:
public Person getPersonByName(String firstName, String lastName) { String sql = "SELECT first_name, last_name, email, city FROM PERSON WHERE first_name = ? AND last_name = ?"; try { return jdbcTemplate.queryForObject(sql, new PersonRowMapper(), firstName, lastName); } catch (EmptyResultDataAccessException e) { return null; } }
步骤3:Controller层完善参数校验并调用服务层
拆分参数时要处理格式错误的情况(如无-、拆分后参数不足2个),避免数组越界:
@RestController @RequestMapping("/api/persons") public class PersonController { @Autowired private PersonService personService; @GetMapping public ResponseEntity<Person> getPerson(@RequestParam String fullName) { String[] nameParts = fullName.split("-"); if (nameParts.length != 2) { // 参数格式错误,返回400 return ResponseEntity.badRequest().body(null); } String firstName = nameParts[0]; String lastName = nameParts[1]; Person person = personService.getPersonByName(firstName, lastName); if (person == null) { // 未找到记录,返回404 return ResponseEntity.notFound().build(); } return ResponseEntity.ok(person); } }
注意事项
- 实体类必须提供无参构造方法(
BeanPropertyRowMapper依赖它实例化对象) - 所有字段必须实现getter和setter方法(自动映射需通过这些方法赋值)
- 捕获
EmptyResultDataAccessException:查询结果为空时JdbcTemplate会抛出该异常,需手动处理避免接口报错
内容的提问来源于stack exchange,提问作者Kevin Johnson
相关产品推荐
相关产品推荐

