maven+vue+servlet+element+MyBatis 前后端分离小项目

2022-03-07 17:54:41 浏览数 (1)

准备工作

需要的文件我已经打包好了:

链接:https://pan.baidu.com/s/1gTIi2nTHHv3bfcy5khKxgw

提取码:i2al

  • 前端页面:可参考此篇文章 Element 入门教程 自行编写,也可以直接使用我准备好的模板
  • sql 文件 ```sql -- 创建数据库 create database db1 character set utf8; use db1;
代码语言:txt复制
-- 删除tb_brand表
代码语言:txt复制
drop table if exists tb_brand;
代码语言:txt复制
-- 创建tb_brand表
代码语言:txt复制
create table tb_brand
代码语言:txt复制
(
代码语言:txt复制
    -- id 主键
代码语言:txt复制
    id           int primary key auto_increment,
代码语言:txt复制
    -- 品牌名称
代码语言:txt复制
    brand_name   varchar(20),
代码语言:txt复制
    -- 企业名称
代码语言:txt复制
    company_name varchar(20),
代码语言:txt复制
    -- 排序字段
代码语言:txt复制
    ordered      int,
代码语言:txt复制
    -- 描述信息
代码语言:txt复制
    description  varchar(100),
代码语言:txt复制
    -- 状态:0:禁用  1:启用
代码语言:txt复制
    status       int
代码语言:txt复制
);
代码语言:txt复制
-- 添加数据
代码语言:txt复制
insert into tb_brand (brand_name, company_name, ordered, description, status)
代码语言:txt复制
values 
代码语言:txt复制
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
代码语言:txt复制
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
代码语言:txt复制
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
代码语言:txt复制
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1)
代码语言:txt复制
        ;
代码语言:txt复制
SELECT * FROM tb_brand;
代码语言:txt复制
```

业务 - 查询所有

后端

  • BrandMapper.java:这里要注意实体类属性名称和数据库表名称不一致,使用 resultMap 映射 ```java /** * 查询所有 * @return */ @Select("select * from tb_brand") @ResultMap("brandResultMap") List<Brand> selectAll(); ```
  • service - service 接口:BrandService.java ```java package com.ruochen.service;
代码语言:txt复制
import com.ruochen.pojo.Brand;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
public interface BrandService {
代码语言:txt复制
    /**
代码语言:txt复制
     * 查询所有
     * @return
     */
    List<Brand> selectAll();
}
```
- service 实现类:`BrandServiceImpl.java`
```java
package com.ruochen.service.impl;
代码语言:txt复制
import com.ruochen.mapper.BrandMapper;
代码语言:txt复制
import com.ruochen.pojo.Brand;
代码语言:txt复制
import com.ruochen.service.BrandService;
代码语言:txt复制
import com.ruochen.util.SqlSessionFactoryUtils;
代码语言:txt复制
import org.apache.ibatis.session.SqlSession;
代码语言:txt复制
import org.apache.ibatis.session.SqlSessionFactory;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
public class BrandServiceImpl implements BrandService {
代码语言:txt复制
    // 1. 创建 SqlSessionFactory 工厂对象
代码语言:txt复制
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
代码语言:txt复制
    @Override
代码语言:txt复制
    public List<Brand> selectAll() {
代码语言:txt复制
        // 2. 获取 SqlSession 对象
代码语言:txt复制
        SqlSession sqlSession = factory.openSession();
代码语言:txt复制
        // 3. 获取 BrandMapper
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 调用方法
代码语言:txt复制
        List<Brand> brands = brandMapper.selectAll();
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
        return brands;
代码语言:txt复制
    }
代码语言:txt复制
}
代码语言:txt复制
```
  • SelectAllServlet.java ```java package com.ruochen.web.servlet;
代码语言:txt复制
import com.alibaba.fastjson.JSON;
代码语言:txt复制
import com.ruochen.pojo.Brand;
代码语言:txt复制
import com.ruochen.service.BrandService;
代码语言:txt复制
import com.ruochen.service.impl.BrandServiceImpl;
代码语言:txt复制
import javax.servlet.*;
代码语言:txt复制
import javax.servlet.http.*;
代码语言:txt复制
import javax.servlet.annotation.*;
代码语言:txt复制
import java.io.IOException;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
@WebServlet("/selectAllServlet")
代码语言:txt复制
public class SelectAllServlet extends HttpServlet {
代码语言:txt复制
    private BrandService brandService = new BrandServiceImpl();
代码语言:txt复制
    @Override
代码语言:txt复制
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
代码语言:txt复制
        // 1. 调用 service 查询
代码语言:txt复制
        List<Brand> brands = brandService.selectAll();
代码语言:txt复制
        // 2. 数据转为 JSON
代码语言:txt复制
        String jsonString = JSON.toJSONString(brands);
代码语言:txt复制
        // 3. 写数据
代码语言:txt复制
        // 数据存在中文
代码语言:txt复制
        response.setContentType("text/json;charset=utf-8");
代码语言:txt复制
        response.getWriter().write(jsonString);
代码语言:txt复制
    }
代码语言:txt复制
    @Override
代码语言:txt复制
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
代码语言:txt复制
        this.doGet(request, response);
代码语言:txt复制
    }
代码语言:txt复制
}
代码语言:txt复制
```
  • 测试

前端

  • 页面加载完成后,发送异步请求,获取数据,绑定表格上模型 tableData ```js mounted() { // 当页面加载完成后,发送异步请求,获取数据 var _this = this; axios({ method: "get", url: "http://localhost:8080/brand-case/selectAllServlet" }).then(function (resp) { _this.tableData = resp.data; }) }, ```
  • 测试 业务 - 新增品牌

后端

  • BrandMapper.java ```java /** * 添加数据 * @param brand */ @Insert("insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status})") void add(Brand brand); ```
  • service - service 接口:BrandService.java ```java /** * 添加数据 * @param brand */ void add(Brand brand); ``` - service 实现类:`BrandServiceImpl.java` ```java @Override public void add(Brand brand) { // 2. 获取 SqlSession 对象 SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 brandMapper.add(brand); // 5. 提交事务 sqlSession.commit(); // 6. 释放资源 sqlSession.close(); } } ```
  • AddServlet.java ```java package com.ruochen.web.servlet;
代码语言:txt复制
import com.alibaba.fastjson.JSON;
代码语言:txt复制
import com.ruochen.pojo.Brand;
代码语言:txt复制
import com.ruochen.service.BrandService;
代码语言:txt复制
import com.ruochen.service.impl.BrandServiceImpl;
代码语言:txt复制
import javax.servlet.ServletException;
代码语言:txt复制
import javax.servlet.annotation.WebServlet;
代码语言:txt复制
import javax.servlet.http.HttpServlet;
代码语言:txt复制
import javax.servlet.http.HttpServletRequest;
代码语言:txt复制
import javax.servlet.http.HttpServletResponse;
代码语言:txt复制
import java.io.BufferedReader;
代码语言:txt复制
import java.io.IOException;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
@WebServlet("/addServlet")
代码语言:txt复制
public class AddServlet extends HttpServlet {
代码语言:txt复制
    private BrandService brandService = new BrandServiceImpl();
代码语言:txt复制
    @Override
代码语言:txt复制
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
代码语言:txt复制
        // 1. 接收品牌数据
代码语言:txt复制
        BufferedReader br = request.getReader();
代码语言:txt复制
        String params = br.readLine();  // json 字符串
代码语言:txt复制
        // JSON 字符串转为 brand 对象
代码语言:txt复制
        Brand brand = JSON.parseObject(params, Brand.class);
代码语言:txt复制
        // 2. 调用 service 添加
代码语言:txt复制
        brandService.add(brand);
代码语言:txt复制
        // 3. 响应成功标识
代码语言:txt复制
        response.getWriter().write("success");
代码语言:txt复制
    }
代码语言:txt复制
    @Override
代码语言:txt复制
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
代码语言:txt复制
        this.doGet(request, response);
代码语言:txt复制
    }
代码语言:txt复制
}
代码语言:txt复制
```

前端

  • 我们先将上一个功能中查询所有数据 ajax 请求封装为一个方法,方便调用 ```js // 查询所有数据 selectAll() { // 当页面加载完成后,发送异步请求,获取数据 var _this = this; axios({ method: "get", url: "http://localhost:8080/brand-case/selectAllServlet" }).then(function (resp) { _this.tableData = resp.data; }) }, ```
  • 提交按钮绑定了 addBrand 方法,点击提交按钮时发送 ajax 请求,添加数据(数据由模型 brand 绑定获得) ```js // 添加数据 addBrand() { var _this = this; // 发送 ajax 请求,添加数据 axios({ method: "post", url: "http://localhost:8080/brand-case/addServlet", data: _this.brand }).then(function (resp) { if (resp.data == 'success') { // 添加成功 // 关闭窗口 _this.dialogVisible = false; // 查询数据 _this.selectAll();
代码语言:txt复制
            // 弹出消息提示
代码语言:txt复制
			_this.$message({
代码语言:txt复制
			     message: '恭喜你,添加成功',
代码语言:txt复制
			     type: 'success'
代码语言:txt复制
			});
代码语言:txt复制
        }
代码语言:txt复制
    })
代码语言:txt复制
},
代码语言:txt复制
```

Servlet 优化

  • 查看文章:Javaweb 自定义 Servlet 实现按照访问路径转发

业务 - 批量删除

后端

  • Dao 层 - BrandMapper.java ```java /** * 批量删除 * @param ids */ void deleteByIds(@Param("ids") int[] ids); ``` - `BrandMapper.xml` ```xml <!--批量删除--> <delete id="deleteByIds"> delete from tb_brand where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete> ```
  • Service 层 - Service 接口:BrandService.java ```java /** * 批量删除 * @param ids */ void deleteByIds(int[] ids); ``` - Service 实现类:`BrandServiceImpl.java` ```java @Override public void deleteByIds(int[] ids) { // 2. 获取 SqlSession 对象 SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 brandMapper.deleteByIds(ids); // 5. 提交事务 sqlSession.commit(); // 6. 释放资源 sqlSession.close(); } ```
  • Web 层:BrandServlet.java ```java /** * 批量删除 * * @param request * @param response * @throws ServletException * @throws IOException */ public void deleteByIds(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收数据 [1,2,...] BufferedReader br = request.getReader(); String params = br.readLine(); // json 字符串
代码语言:txt复制
        // 转为 int[]
代码语言:txt复制
        int[] ids = JSON.parseObject(params, int[].class);
代码语言:txt复制
        // 2. 调用 service 添加
代码语言:txt复制
        brandService.deleteByIds(ids);
代码语言:txt复制
        // 3. 响应成功标识
代码语言:txt复制
        response.getWriter().write("success");
代码语言:txt复制
    }
代码语言:txt复制
```

前端

  • 首先要给批量删除按钮添加点击事件 ```html <el-button type="danger" plain @click="deleteByIds">批量删除</el-button> ```
  • 在编写 deleteByIds 方法之前,我们要想办法获取到选中的 id,复选框选中后会执行一个 handleSelectionChange 回调方法,我们可以通过该方法中的 this.multipleSelection 获取到选中的对象数组 ```js // 复选框选中后执行的方法 handleSelectionChange(val) { this.multipleSelection = val;
代码语言:txt复制
    // console.log(this.multipleSelection)
代码语言:txt复制
},
代码语言:txt复制
```
  • 然后我们再写一个模型 multipleSelection 用于存放从 this.multipleSelection 获取到的 id ```js // 复选框选中数据集合 multipleSelection: [], ```
  • 现在我们编写 deleteByIds 方法 ```js // 批量删除 deleteByIds() { // 弹出确认提示框 this.$confirm('此操作将删除该数据, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { // 用户点击确认按钮 // 1. 创建id 数组 从 this.multipleSelection 获取即可 for (let selectionElement of this.multipleSelection) { this.selectedIds.push(selectionElement.id); } // 2. 发送 ajax 请求,携带 ID var _this = this; // 发送 ajax 请求,添加数据 axios({ method: "post", url: "http://localhost:8080/brand-case/brand/deleteByIds", data: _this.selectedIds }).then(function (resp) { if (resp.data == 'success') { // 删除成功 // 重新查询数据 _this.selectAll();
代码语言:txt复制
                // 弹出消息提示
代码语言:txt复制
                _this.$message({
代码语言:txt复制
                    message: '恭喜你,删除成功',
代码语言:txt复制
                    type: 'success'
代码语言:txt复制
                });
代码语言:txt复制
            }
代码语言:txt复制
        })
代码语言:txt复制
    }).catch(() => {
代码语言:txt复制
        // 用户点击取消按钮
代码语言:txt复制
        this.$message({
代码语言:txt复制
            type: 'info',
代码语言:txt复制
            message: '已取消删除'
代码语言:txt复制
        });
代码语言:txt复制
    });
代码语言:txt复制
}
代码语言:txt复制
```

业务 - 分页查询

分析

  • SQL Limit 查询语句 - 参数1:开始索引 - 参数2:查询的条目数
  • 页面传递的参数 - 当前页码 - 每页显示条数
  • 计算 - 开始索引 = (当前页码 - 1) * 每页显示条数 - 查询的条目数 = 每页显示条数

后端

  • 创建 JavaBean:PageBean.java ```java package com.ruochen.pojo;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
// 分页查询的 JavaBean
代码语言:txt复制
public class PageBean<T> {
代码语言:txt复制
    // 总记录数
代码语言:txt复制
    private int totalCount;
代码语言:txt复制
    // 当前页数据
代码语言:txt复制
    private List<T> rows;
代码语言:txt复制
    public int getTotalCount() {
代码语言:txt复制
        return totalCount;
代码语言:txt复制
    }
代码语言:txt复制
    public void setTotalCount(int totalCount) {
代码语言:txt复制
        this.totalCount = totalCount;
代码语言:txt复制
    }
代码语言:txt复制
    public List<T> getRows() {
代码语言:txt复制
        return rows;
代码语言:txt复制
    }
代码语言:txt复制
    public void setRows(List<T> rows) {
代码语言:txt复制
        this.rows = rows;
代码语言:txt复制
    }
代码语言:txt复制
}
代码语言:txt复制
```
  • Dao 层:BrandMapper.java ```java /** * 分页查询 * * @param begin 开始索引 * @param size 查询数据条数 * @return */ @Select("select * from tb_brand limit #{begin}, #{size}") @ResultMap("brandResultMap") List<Brand> selectByPage(@Param("begin") int begin, @Param("size") int size);
代码语言:txt复制
    /**
代码语言:txt复制
     * 查询总记录数
     *
     * @return
     */
    @Select("select count(*) from tb_brand")
    int selectTotalCount();
```Service 层
		- Service 接口类:
代码语言:txt复制
        // 4. 计算 开始索引 和 查询条目数
代码语言:txt复制
        int begin = (currentPage - 1) * pageSize;
代码语言:txt复制
        int size = pageSize;
代码语言:txt复制
        // 5. 查询当前页数据
代码语言:txt复制
        List<Brand> rows = brandMapper.selectByPage(begin, size);
代码语言:txt复制
        // 6. 查询总记录数
代码语言:txt复制
        int totalCount = brandMapper.selectTotalCount();
代码语言:txt复制
        // 7. 封装 pageBean 对象
代码语言:txt复制
        PageBean<Brand> pageBean = new PageBean<>();
代码语言:txt复制
        pageBean.setRows(rows);
代码语言:txt复制
        pageBean.setTotalCount(totalCount);
代码语言:txt复制
        // 8. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
        return pageBean;
代码语言:txt复制
    }
代码语言:txt复制
```
  • Web 层:BrandServlet.java ```java /** * 分页查询 * * @param request * @param response * @throws ServletException * @throws IOException */ public void selectByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收 当前页码 和 每页展示条数 url?currentPage=1&pageSize=5 String _currentPage = request.getParameter("currentPage"); String _pageSize = request.getParameter("pageSize");
代码语言:txt复制
        // 转换为 int 类型
代码语言:txt复制
        int currentPage = Integer.parseInt(_currentPage);
代码语言:txt复制
        int pageSize = Integer.parseInt(_pageSize);
代码语言:txt复制
        // 2. 调用 Service 查询
代码语言:txt复制
        PageBean<Brand> pageBean = brandService.selectByPage(currentPage, pageSize);
代码语言:txt复制
        // 2. 数据转为 JSON
代码语言:txt复制
        String jsonString = JSON.toJSONString(pageBean);
代码语言:txt复制
        // 3. 写数据
代码语言:txt复制
        // 数据存在中文
代码语言:txt复制
        response.setContentType("text/json;charset=utf-8");
代码语言:txt复制
        response.getWriter().write(jsonString);
代码语言:txt复制
    }
代码语言:txt复制
```
  • 测试 前端
  • 设置模型总记录数:totalCount,初值设为100,在selectAll方法中赋值
  • 当前页码模型 currentPage 初值设置为1
  • 每页条数模型 pageSize,默认值为 5 ```js // 每页显示条数 pageSize: 5, // 总记录数 totalCount: 100, // 当前页码 currentPage: 1, ```
  • currentPage 和 pageSize 动态拼接到 selectAll url 中
  • selectAll 方法改为查询分页 ```java // 查询分页数据 var _this = this; axios({ method: "get", url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" this.currentPage "&pageSize=" this.pageSize, }).then(function (resp) { // 设置表格数据 _this.tableData = resp.data.rows; // 设置总记录数 _this.totalCount = resp.data.totalCount; }) ```
  • 分页工具条绑定了 handleCurrentChangehandleSizeChange 方法,方法中将值设置到模型中,再调用 selectAll 方法即可 ```js //分页 handleSizeChange(val) { // console.log(`每页 ${val} 条`); // 重新设置每页显示条数 this.pageSize = val; // 重新查询 this.selectAll(); }, handleCurrentChange(val) { // console.log(`当前页: ${val}`); // 重新设置当前页码 this.currentPage = val; // 重新查询 this.selectAll(); }, ```

业务 - 条件查询

后端

在这里插入图片描述在这里插入图片描述
  • Dao 层 - BrandMapper.java ```java /** * 分页条件查询 * * @param begin 开始索引 * @param size 查询数据条数 * @param brand 查询条件 * @return */ @ResultMap("brandResultMap") List<Brand> selectByPageAndCondition(@Param("begin") int begin, @Param("size") int size, @Param("brand") Brand brand);
代码语言:txt复制
    /**
代码语言:txt复制
     * 根据条件查询总记录数
     *
     * @param brand 查询条件
     * @return
     */
    int selectTotalCountByCondition(Brand brand);
```
- `BrandMapper.xml`
```xml
    <select id="selectByPageAndCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        <where>
            <if test="brand.brandName != null and brand.brandName != ''">
                and brand_name like #{brand.brandName}
            </if>
            <if test="brand.companyName != null and brand.companyName != ''">
                and company_name like #{brand.companyName}
            </if>
            <if test="brand.status != null">
                and status like #{brand.status}
            </if>
        </where>
        limit #{begin}, #{size}
    </select>
代码语言:txt复制
    <select id="selectTotalCountByCondition" resultType="java.lang.Integer">
代码语言:txt复制
        select count(*)
代码语言:txt复制
        from tb_brand
代码语言:txt复制
        <where>
代码语言:txt复制
            <if test="brandName != null and brandName != ''">
代码语言:txt复制
                and brand_name like #{brandName}
代码语言:txt复制
            </if>
代码语言:txt复制
            <if test="companyName != null and companyName != ''">
代码语言:txt复制
                and company_name like #{companyName}
代码语言:txt复制
            </if>
代码语言:txt复制
            <if test="status != null">
代码语言:txt复制
                and status like #{status}
代码语言:txt复制
            </if>
代码语言:txt复制
        </where>
代码语言:txt复制
    </select>
代码语言:txt复制
```
  • Service 层 - Service 接口类:BrandService.java ```java /** * 分页条件查询 * * @param currentPage * @param pageSize * @param brand * @return */ PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand); ```
代码语言:txt复制
- Service 实现类:`BrandServiceImpl.java`
```java
    @Override
    public PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand) {
        // 2. 获取 SqlSession 对象
        SqlSession sqlSession = factory.openSession();
        // 3. 获取 BrandMapper
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 计算 开始索引 和 查询条目数
代码语言:txt复制
        int begin = (currentPage - 1) * pageSize;
代码语言:txt复制
        int size = pageSize;
代码语言:txt复制
        // 处理 brand 条件,模糊表达式
代码语言:txt复制
        String brandName = brand.getBrandName();
代码语言:txt复制
        if (brandName != null && brandName.length() > 0) {
代码语言:txt复制
            brand.setBrandName("%"   brandName   "%");
代码语言:txt复制
        }
代码语言:txt复制
        String companyName = brand.getCompanyName();
代码语言:txt复制
        if (companyName != null && companyName.length() > 0) {
代码语言:txt复制
            brand.setCompanyName("%"   companyName   "%");
代码语言:txt复制
        }
代码语言:txt复制
        // 5. 查询当前页数据
代码语言:txt复制
        List<Brand> rows = brandMapper.selectByPageAndCondition(begin, size, brand);
代码语言:txt复制
        // 6. 查询总记录数
代码语言:txt复制
        int totalCount = brandMapper.selectTotalCountByCondition(brand);
代码语言:txt复制
        // 7. 封装 pageBean 对象
代码语言:txt复制
        PageBean<Brand> pageBean = new PageBean<>();
代码语言:txt复制
        pageBean.setRows(rows);
代码语言:txt复制
        pageBean.setTotalCount(totalCount);
代码语言:txt复制
        // 8. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
        return pageBean;
代码语言:txt复制
    }
代码语言:txt复制
```
  • Web 层:BrandServlet.java ```java /** * 分页条件查询 * * @param request * @param response * @throws ServletException * @throws IOException */ public void selectByPageAndCondition(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收 当前页码 和 每页展示条数 url?currentPage=1&pageSize=5 String _currentPage = request.getParameter("currentPage"); String _pageSize = request.getParameter("pageSize");
代码语言:txt复制
        // 转换为 int 类型
代码语言:txt复制
        int currentPage = Integer.parseInt(_currentPage);
代码语言:txt复制
        int pageSize = Integer.parseInt(_pageSize);
代码语言:txt复制
        // 获取查询条件对象
代码语言:txt复制
        BufferedReader br = request.getReader();
代码语言:txt复制
        String params = br.readLine();  // json 字符串
代码语言:txt复制
        // 转为 brand 对象
代码语言:txt复制
        Brand brand = JSON.parseObject(params, Brand.class);
代码语言:txt复制
        // 2. 调用 Service 查询
代码语言:txt复制
        PageBean<Brand> pageBean = brandService.selectByPageAndCondition(currentPage, pageSize, brand);
代码语言:txt复制
        // 2. 数据转为 JSON
代码语言:txt复制
        String jsonString = JSON.toJSONString(pageBean);
代码语言:txt复制
        // 3. 写数据
代码语言:txt复制
        // 数据存在中文
代码语言:txt复制
        response.setContentType("text/json;charset=utf-8");
代码语言:txt复制
        response.getWriter().write(jsonString);
代码语言:txt复制
    }
代码语言:txt复制
```

前端

  • 搜索框绑定模型 brand ```html <!--搜索表单--> <el-form :inline="true" :model="brand" class="demo-form-inline"> ```
  • 给按钮绑定单击事件 onSubmit ,调用 selectAll 方法,这里我们就要给后台携带 brand 参数(post 方式),但是我们还需要在 url 中携带 currentPage 和 pageSize 参数(get方式),需要同时传输 post 和 get 数据,所以把请求方式改为 post ```js // 查询分页数据 var _this = this; axios({ method: "post", url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" this.currentPage "&pageSize=" this.pageSize, data: this.brand }).then(function (resp) { // 设置表格数据 _this.tableData = resp.data.rows; // 设置总记录数 _this.totalCount = resp.data.totalCount; }) ```
  • onSubmit ```js this.currentPage = 1; ```
  • 最后,测试时我们发现 status 显示的仍然是数字,我们要让其显示 启动/禁用,我们在 Brand.java 里面有逻辑视图 getStatusStr,所以在前端页面表格中当前状态 prpostatusStr 即可 ```html <el-table-column prop="statusStr" align="center" label="当前状态"> </el-table-column> ```

业务 - 删除功能

后端

  • Dao 层:BrandMapper.java ```java /** * 删除操作 * @param id */ @Delete("delete from tb_brand where id = #{id}") void deleteById(int id); ```
  • Service 层 - Service 接口类:BrandService.java ```java /** * 删除 * @param id */ void deleteById(int id); ``` - Service 实现类:`BrandServiceImpl.java` ```java @Override public void deleteById(int id) { // 2. 获取 SqlSession 对象 SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 brandMapper.deleteById(id); // 5. 提交事务 sqlSession.commit(); // 6. 释放资源 sqlSession.close(); } ```
  • Web 层:BrandServlet.java,这里我们不需要单独编写根据 id 删除的 servlet,直接调用 deleteByIdIds 即可前端
  • 删除操作前端要返回给后端删除数据的 id,这里我们通过 template 参数 scope 可以获取到当前行的数据,然后从数据中取出 id,携带 id 通过 axios 向后端发起请求即可 ```html <el-table-column align="center" label="操作"> <template slot-scope="scope"> <el-row> <el-button type="primary">修改</el-button> <el-button type="danger" @click="deleteById(scope.row)">删除</el-button> </el-row> </template> </el-table-column> ``` ```js // 根据Id 删除 deleteById(row) { this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { // 用户点击确认按钮 let rowId = [row.id]; // 发送 ajax 请求,携带 id axios({ method: "pose", url: "http://localhost:8080/brand-case/brand/deleteByIds", data: rowId }).then(resp => { if (resp.data == 'success') { // 删除成功 // 重新查询数据 this.selectAll();
代码语言:txt复制
                // 弹出消息提示
代码语言:txt复制
                this.$message({
代码语言:txt复制
                    message: '恭喜你,删除成功',
代码语言:txt复制
                    type: 'success'
代码语言:txt复制
                });
代码语言:txt复制
            }
代码语言:txt复制
        })
代码语言:txt复制
    }).catch(() => {
代码语言:txt复制
        this.$message({
代码语言:txt复制
            type: 'info',
代码语言:txt复制
            message: '已取消删除'
代码语言:txt复制
        });
代码语言:txt复制
    });
代码语言:txt复制
}
代码语言:txt复制
```

业务 - 修改功能

后端

  • Dao 层:BrandMapper.java ```java /** * 更新操作 * * @param brand */ @Update("update tb_brand set brand_name = #{brandName}, company_name = #{companyName}, ordered = #{ordered}, " "description = #{description}, status = #{status} where id = #{id}") void update(Brand brand); ```
  • Service 层 - Service 接口类:BrandService.java ```java /** * 修改 * @param brand */ void update(Brand brand); ``` - Service 实现类:`BrandServiceImpl.java` ```java @Override public void update(Brand brand) { // 2. 获取 SqlSession 对象 SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 brandMapper.update(brand); // 5. 提交事务 sqlSession.commit(); // 6. 释放资源 sqlSession.close(); } ``` - Web 层:`BrandServlet.java` ```java /** * 更新操作 * * @param request * @param response * @throws ServletException * @throws IOException */ public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收品牌数据 BufferedReader br = request.getReader(); String params = br.readLine(); // json 字符串
代码语言:txt复制
        // JSON 字符串转为 brand 对象
代码语言:txt复制
        Brand brand = JSON.parseObject(params, Brand.class);
代码语言:txt复制
        // 2. 调用 service 添加
代码语言:txt复制
        brandService.update(brand);
代码语言:txt复制
        // 3. 响应成功标识
代码语言:txt复制
        response.getWriter().write("success");
代码语言:txt复制
    }
代码语言:txt复制
```

前端

  • 首先,我们要新建一个 dialog 来进行数据回显(不用直接用新增数据的 dialog 的原因是新增 dialog 绑定的模型 brand 在搜索框也有绑定,直接使用会出现乱七八糟的问题),同时绑定模型 updateBrand ```html <!--更新数据对话框表单--> <el-dialog title="更新品牌" :visible.sync="updateVisible" width="30%" >
代码语言:txt复制
    <el-form ref="form" :model="updateBrand" label-width="80px">
代码语言:txt复制
        <el-form-item label="品牌名称">
代码语言:txt复制
            <el-input v-model="updateBrand.brandName"></el-input>
代码语言:txt复制
        </el-form-item>
代码语言:txt复制
        <el-form-item label="企业名称">
代码语言:txt复制
            <el-input v-model="updateBrand.companyName"></el-input>
代码语言:txt复制
        </el-form-item>
代码语言:txt复制
        <el-form-item label="排序">
代码语言:txt复制
            <el-input v-model="updateBrand.ordered"></el-input>
代码语言:txt复制
        </el-form-item>
代码语言:txt复制
        <el-form-item label="备注">
代码语言:txt复制
            <el-input type="textarea" v-model="updateBrand.description"></el-input>
代码语言:txt复制
        </el-form-item>
代码语言:txt复制
        <el-form-item label="状态">
代码语言:txt复制
            <el-switch v-model="updateBrand.status"
代码语言:txt复制
                       active-value="1"
代码语言:txt复制
                       inactive-value="0"
代码语言:txt复制
            ></el-switch>
代码语言:txt复制
        </el-form-item>
代码语言:txt复制
        <el-form-item>
代码语言:txt复制
            <el-button type="primary" @click="updateByBrand">提交</el-button>
代码语言:txt复制
            <el-button @click="updateVisible = false">取消</el-button>
代码语言:txt复制
        </el-form-item>
代码语言:txt复制
    </el-form>
代码语言:txt复制
</el-dialog>
代码语言:txt复制
```
  • updateBrand 模型 和 updateVisible 定义如下 ```js // 更新brand updateBrand: { status: '', brandName: '', companyName: '', id: "", ordered: "", description: "" }, // 更新数据对话框是否展示的标记 updateVisible: false, ```
  • 在修改按钮通过 slot-scopescope.row 获取选中行数据 ```html <el-table-column align="center" label="操作"> <template slot-scope="scope"> <el-row> <el-button type="primary" @click="update(scope.row)">修改</el-button> <el-button type="danger" @click="deleteById(scope.row)">删除</el-button> </el-row> </template> </el-table-column> ```
  • 修改按钮绑定 update 方法,进行数据回显 ```js // 数据回显 update(row) { // 数据回显 this.updateBrand = { status: row.status, brandName: row.brandName, companyName: row.companyName, id: row.id, ordered: row.ordered, description: row.description }; // 打开窗口 this.updateVisible = true; }, ```
  • update dialog 绑定 updateByBrand 方法,进行更新操作 ```js // 更新数据 updateByBrand() { // 发送 ajax 请求,添加数据 axios({ method: "post", url: "http://localhost:8080/brand-case/brand/update", data: this.updateBrand }).then(resp => { if (resp.data == 'success') { // 添加成功 // 关闭窗口 this.updateVisible = false; // 重新查询数据 this.selectAll();
代码语言:txt复制
            // 弹出消息提示
代码语言:txt复制
            this.$message({
代码语言:txt复制
                message: '恭喜你,更新成功',
代码语言:txt复制
                type: 'success'
代码语言:txt复制
            });
代码语言:txt复制
        }
代码语言:txt复制
    })
代码语言:txt复制
}
代码语言:txt复制
```

问题:status(switch开关)回显有问题,目前不会实现

前端代码优化

  • 最后,我们对 axios 进行一下优化,之前我们的异步请求代码是这样的 ```js var _this = this; axios({ method: "post", url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" this.currentPage "&pageSize=" this.pageSize, data: this.brand }).then(function (resp) { // 设置表格数据 _this.tableData = resp.data.rows; // 设置总记录数 _this.totalCount = resp.data.totalCount; }) ```
  • 因为在 axios 中 this 指代的是 axios 而不是 vue,我们每次都需要在 axios 外面先将指代 vue 的 this 赋值给 _this,然后在 axios 中使用 _this 调用 vue 中的模型,这样很不方便
  • 我们可以将 axios then 的 function 改为箭头函数,箭头函数中 this 会根据上下文语义进行判断,这样就可以代表 vue 对象,修改如下```js axios({ method: "post", url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" this.currentPage "&pageSize=" this.pageSize, data: this.brand }).then(resp => { // 设置表格数据 this.tableData = resp.data.rows; // 设置总记录数 this.totalCount = resp.data.totalCount; }) ```最后的成品我也打包放在了网盘,需要可以自行下载 链接:https://pan.baidu.com/s/1Ps3parEeOJtazS-Kv7bWEw 提取码:msjj

觉得本文还不错可以点个赞支持一下 :smile:

0 人点赞