赞
踩
目录
1. Invalid bound statement (not found)
2. Unable to find a @SpringBootConfiguration,you need to use @ContextConfiguration
3. Mapped Statements already contains value: com.itheima.mapper.DeptMapper.selectList
4. Bad Sql Grammer... You have a error in your sql Syntax
所有的项目规范,==并非==全世界统一的强制性规范。实际开发中,可能每个项目组都有自己的一套规范
接收请求路径里的变量参数:@PathVariable("占位符名称")
接收不同请求方式的请求:
@GetMpping
@PostMapping
@PutMapping
@DeleteMapping
我们这次案例练习里,所有Controller的方法返回值,统一都是Result
类型
企业开发中,通常是要输出日志,为将来程序出bug之后,找线索做准备
传统的方式:在类里添加以下代码,然后才可以使用log.info()
, log.warn()
, log.error()
等方法
private static final Logger log = LoggerFactory.getLogger(当前类名.class);
例如:
- @RestController
- public class DeptController {
- private static final Logger log = LoggerFactory.getLogger(DeptController.class);
-
- @GetMapping("xxx/{id}")
- public Result xxx(@PathVariable("id") String id){
- //打印日志:根据id查询部门,id=id值
- log.info("根据id查询部门,id={}", id);
- //完成功能代码……
- return null;
- }
- }
可以使用Lombok简化一下:
在类上添加注解 @Slf4j
在方法里就可以直接使用log
对象输出日志了:可以使用log.info()
, log.warn()
, log.error()
等方法
- @Slf4j
- @RestController
- public class DeptController {
-
- @GetMapping("xxx/{id}")
- public Result xxx(@PathVariable("id") String id){
- //打印日志:根据id查询部门,id=id值
- log.info("根据id查询部门,id={}", id);
- //完成功能代码……
- return null;
- }
- }
在SpringBoot配置文件里加上:
- #logging.level,包名=日志级别 表示指定包下的程序类,只输出指定级别以上的日志
-
- logging.level.com.itheima=error
DeptController:
- package com.itheima.controller;
-
- import com.itheima.pojo.Dept;
- import com.itheima.pojo.Emp;
- import com.itheima.pojo.Result;
- import com.itheima.service.DeptService;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
-
- import java.util.List;
-
- /**
- * 通常会在Controller类上加@RequestMapping("所有方法的路径前缀")
- * 然后每个方法上再添加@RequestMapping、@PostMapping、@PutMapping、@DeleteMapping,只需要加后边剩下的那一截路径即可
- * 比如:
- * 类上配置是@RequestMapping("/depts")
- * 方法上的配置是@GetMapping("/{id}")
- * 这时候,此方法的访问路径是:类的路径 + 方法的路径,即: /depts/{id}
- *
- * 部门管理Controller
- */
- @Slf4j
- @RestController
- @RequestMapping("/depts")
- public class DeptController {
- @Autowired
- private DeptService deptService;
-
- @GetMapping
- public Result queryAllDeppts(){
- log.info("查询所有部门");
- List<Dept> empList = deptService.queryAllDepts();
- return Result.success(empList);
- }
- }
DeptService:
- package com.itheima.service;
-
- import com.itheima.pojo.Dept;
- import com.itheima.pojo.Emp;
-
- import java.util.List;
-
- /**
- * 部门管理
- */
- public interface DeptService {
- List<Dept> queryAllDepts();
- }
DeptServiceImpl:
- package com.itheima.service.impl;
-
- import com.itheima.mapper.DeptMapper;
- import com.itheima.pojo.Dept;
- import com.itheima.pojo.Emp;
- import com.itheima.service.DeptService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
- import java.time.LocalDateTime;
- import java.util.List;
-
- @Service
- public class DeptServiceImpl implements DeptService {
- @Autowired
- private DeptMapper deptMapper;
-
- @Override
- public List<Dept> queryAllDepts() {
- return deptMapper.selectAll();
- }
- }
DeptMapper:
- package com.itheima.mapper;
-
- import com.itheima.pojo.Dept;
- import com.itheima.pojo.Emp;
- import org.apache.ibatis.annotations.Delete;
- import org.apache.ibatis.annotations.Insert;
- import org.apache.ibatis.annotations.Mapper;
- import org.apache.ibatis.annotations.Select;
-
- import java.util.List;
-
- /**
- * 部门管理
- */
- @Mapper
- public interface DeptMapper {
- @Select("select * from dept")
- List<Dept> selectAll();
- }
DeptController:
- @DeleteMapping("/{deptId}")
- public Result deleteDeptById(@PathVariable("deptId") Integer id){
- log.info("根据id删除部门,id={}", id);
- deptService.deleteDeptById(id);
- return Result.success();
- }
DeptService:
void deleteDeptById(Integer id);
DeptServiceImpl:
- @Override
- public void deleteDeptById(Integer id) {
- deptMapper.deleteById(id);
- }
DeptMapper:
- @Delete("delete from dept where id = #{id}")
- void deleteById(Integer id);
DeptController:
- @PostMapping
- public Result addDept(@RequestBody Dept dept){
- log.info("新增部门:{}", dept);
- deptService.addDept(dept);
- return Result.success();
- }
DeptService:
void addDept(Dept dept);
DeptServiceImpl:
- @Override
- public void addDept(Dept dept) {
- //补全数据
- LocalDateTime now = LocalDateTime.now();
- dept.setCreateTime(now);
- dept.setUpdateTime(now);
- deptMapper.insert(dept);
- }
DeptMapper:
- @Insert("INSERT INTO dept (name, create_time, update_time) " +
- "VALUES (#{name}, #{createTime}, #{updateTime})")
- void insert(Dept dept);
DeptController:
- @GetMapping("/depts/{id}")
- public Result findById(@PathVariable("id") Integer id) {
- Dept dept = deptService.findById(id);
- return Result.success(dept);
- }
-
- @PutMapping("/depts")
- public Result edit(@RequestBody Dept dept){
- boolean success = deptService.updateById(dept);
- if (success) {
- return Result.success();
- }else{
- return Result.error("修改部门失败");
- }
- }
DeptService:
- Dept findById(Integer id);
-
- boolean updateById(Dept dept);
DeptServiceImpl:
- @Override
- public Dept findById(Integer id) {
- return deptMapper.findById(id);
- }
-
- @Override
- public boolean updateById(Dept dept) {
- dept.setUpdateTime(LocalDateTime.now());
-
- return deptMapper.updateById(dept);
- }
DeptMapper:
- @Select("select * from dept where id = #{id}")
- Dept findById(Integer id);
-
- @Update("update dept set name=#{name}, update_time=#{updateTime} where id = #{id}")
- boolean updateById(Dept dept);
分页功能介绍
分页查询功能,客户端通常需要我们提供两项数据:
数据列表:用于展示给用户看的数据;用户每次点击某一页的按钮,就要去服务端加载这一页的数据列表
总数量:客户端得到总数量后,可以根据每页几条计算分了多少页,从而显示页码按钮
原始分页功能的实现方式
服务端要准备以上两项数据,需要:
执行SQL语句查询总数量:select count(*) from emp where gender = 1
执行SQL语句查询数据列表:select * from emp where gender = 1 limit 0, 5
存在的问题:
有两条SQL语句,Mapper接口里要写两个方法;
两条SQL语句的where条件相同
PageHelper介绍
分页插件PageHelper官网:MyBatis 分页插件 PageHelper
PageHelper是一款开源的Mybatis插件,可以帮我们简化分页功能的实现
PageHelper的使用
1.添加依赖坐标
- <!--PageHelper分页插件-->
- <dependency>
- <groupId>com.github.pagehelper</groupId>
- <artifactId>pagehelper-spring-boot-starter</artifactId>
- <version>1.4.2</version>
- </dependency>
2.使用方式:在调用Mapper时,按照如下步骤
- //1. 开启分页
- PageHelper.startPage(页码,每页几条);
- //2. 查询列表:SQL语句里不要加limit,只要查询列表就行.
- // 例如 select * from emp where... 不要再加limit
- List<Emp> empList = empMapper.selectList();
- //3. 获取分页结果
- Page<Emp> page = (Page<Emp>)empList;
- long total = page.getTotal(); //获取总数量
PageHelper底层原理:
根据页面提交的搜索条件,分页查询员工列表
EmpController:
- package com.itheima.controller;
-
- import com.itheima.pojo.Emp;
- import com.itheima.pojo.PageBean;
- import com.itheima.pojo.Result;
- import com.itheima.service.EmpService;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.format.annotation.DateTimeFormat;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
-
- import java.time.LocalDate;
-
- /**
- * 员工管理Controller
- */
- @Slf4j
- @RestController
- @RequestMapping("/emps")
- public class EmpController {
- @Autowired
- private EmpService empService;
-
- @GetMapping
- public Result queryEmpsByPage(@RequestParam(value = "page", defaultValue = "1") Integer page,
- @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
- String name, Integer gender,
- @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
- @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){
-
- PageBean<Emp> pageBean = empService.queryEmpsByPage(name, gender, begin, end, page, pageSize);
- return Result.success(pageBean);
- }
- }
EmpService:
- public interface EmpService {
- PageBean<Emp> queryEmpsByPage(String name, Integer gender, LocalDate begin, LocalDate end, Integer page, Integer pageSize);
- }
EmpServiceImpl:
- package com.itheima.service.impl;
-
- import com.github.pagehelper.Page;
- import com.github.pagehelper.PageHelper;
- import com.itheima.mapper.EmpMapper;
- import com.itheima.pojo.Emp;
- import com.itheima.pojo.PageBean;
- import com.itheima.service.EmpService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
- import java.time.LocalDate;
- import java.util.List;
-
- @Service
- public class EmpServiceImpl implements EmpService {
- @Autowired
- private EmpMapper empMapper;
-
- @Override
- public PageBean<Emp> queryEmpsByPage(String name, Integer gender, LocalDate begin, LocalDate end, Integer page, Integer pageSize) {
- //开启分页
- PageHelper.startPage(page, pageSize);
-
- //查询列表
- List<Emp> empList = empMapper.selectList(name, gender, begin, end);
-
- //得到分页结果
- Page<Emp> p = (Page<Emp>) empList;
-
- //封装PageBean对象
- PageBean<Emp> pageBean = new PageBean<>();
- pageBean.setTotal((int) p.getTotal());
- pageBean.setRows(empList);
- return pageBean;
- }
- }
EmpMapper:
- package com.itheima.mapper;
-
- import com.itheima.pojo.Emp;
- import org.apache.ibatis.annotations.Mapper;
-
- import java.time.LocalDate;
- import java.util.List;
-
- /**
- * 员工管理
- */
- @Mapper
- public interface EmpMapper {
- List<Emp> selectList(String name, Integer gender, LocalDate begin, LocalDate end);
- }
EmpMapper.xml:
xml映射文件:要和Mapper接口同名同包
xml内容:
mapper标签的namespace必须是Mapper接口的全限定类名;
select标签的id必须是对应的方法名
select标签必须有resultType,是JavaBean的全限定类名,表示要把查询结果封装成什么类型的对象
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.itheima.mapper.EmpMapper">
- <select id="queryByPage" resultType="com.itheima.pojo.Emp">
- select * from emp
- <where>
- <if test="name!=null and name.length()>0">
- and name like concat('%', #{name}, '%')
- </if>
- <if test="gender!=null">
- and gender = #{gender}
- </if>
- <if test="begin!=null">
- and entrydate >= #{begin}
- </if>
- <if test="end!=null">
- <!-- XML的特殊字符:< 要写成 < -->
- and entrydate <= #{end}
- </if>
- </where>
- </select>
-
- <delete id="deleteByIds">
- delete from emp where id in
- <foreach collection="ids" item="id" separator="," open="(" close=")">
- #{id}
- </foreach>
- </delete>
- </mapper>
EmpController:
- @DeleteMapping("/{ids}")
- public Result batchDeleteEmps(@PathVariable("ids") List<Integer> ids){
- empService.batchDeleteEmps(ids);
- return Result.success();
- }
EmpService:
void batchDeleteEmps(List<Integer> ids);
EmpServiceImpl:
- @Override
- public void batchDeleteEmps(List<Integer> ids) {
- empMapper.batchDeleteByIds(ids);
- }
EmpMapper:
void batchDeleteByIds(List<Integer> ids);
EmpMapper.xml
- <delete id="batchDeleteByIds">
- delete from emp
- <where>
- <if test="ids!=null and ids.size()>0">
- <foreach collection="ids" open="and id in(" item="id" separator="," close=")">
- #{id}
- </foreach>
- </if>
- </where>
- </delete>
原因:Mapper接口里的定义了方法,但是找不到给它配置的SQL语句
解决:如果SQL语句要和方法关联起来,有以下要求,挨个检查确认一下:
XML映射文件,必须和Mapper接口同名同位置
XML里的mapper标签的namespace必须是Mapper接口的全限定类名
XML里配置SQL语句的标签(select, insert, update, delete)的id必须是方法名
在执行单元测试方法时,出现这个错误
原因:单元测试类不在 引导类所在的包 里边。SpringBoot项目的目录结构是有要求的
SpringBoot工程目录结构要求:
引导类所在的包,必须是最大的包。其它所有类(包括单元测试类)必须全部在这个包下边
比如,引导类在com.itheima
包下,那么所有类都必须在这个包下
Controller类、Service类、Mapper类、其它类
单元测试测试类等等
出现的原因,是因为:这个方法有多个SQL语句配置,配置重复了。或者Mapper里的这个方法有重载(同名方法)
Mapper接口里的方法:所有方法不能同名
SQL语句有语法错误,检查SQL语句
web工程:服务端必须启动成功后,然后Postman或者前端界面才可以访问成功
如何启动:运行引导类(启动类),不要运行单元测试类
常见的HTTP错误码
404:找不到资源。需要检查:你的请求路径,在Controller里有没有对应的方法存在
500:服务器内部错误。需要检查:服务端控制台,查看错误信息,根据错误信息定位问题、解决问题
405:Method Not Allowed,请求方式不允许。通常是 客户端发请求的方式,和Controller方法允许的请求方式不匹配
比如:客户端发请求是 DELETE /depts/1
;服务端只有一个方法路径是 @GetMapping("/depts/{id}")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。