目录
环境准备
查询所有功能
添加功能
servlet优化
代码优化
修改品牌
删除品牌
批量删除
分页查询
条件查询
功能介绍
创建表
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(
-- id 主键
id int primary key auto_increment,
-- 品牌名称
brand_name varchar(20),
-- 企业名称
company_name varchar(20),
-- 排序字段
ordered int,
-- 描述信息
description varchar(100),
-- 状态:0:禁用 1:启用
status int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values
('华为', '华为技术有限公司', 100, '万物互联', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
('华为', '华为技术有限公司', 100, '万物互联', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
('华为', '华为技术有限公司', 100, '万物互联', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
('华为', '华为技术有限公司', 100, '万物互联', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
('华为', '华为技术有限公司', 100, '万物互联', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
('华为', '华为技术有限公司', 100, '万物互联', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1),
('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1)
;
/*查询数据*/
SELECT * FROM tb_brand;
如上图所示是查询所有品牌数据在页面展示的效果。要实现这个功能,要先搞明白如下问题:
什么时候发送异步请求?
页面加载完毕后就需要在页面上看到所有的品牌数据。
所以在 mounted() 这个构造函数中写发送异步请求的代码。
请求需要携带参数吗?
查询所有功能不需要携带什么参数。响应的数据格式是什么样?
后端是需要将 List 对象转换为 JSON 格式的数据并响应回给浏览器。
响应数据格式如下:
后端实现
dao方法实现
在 com.green.mapper.BrandMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句
/**
* 查询所有
* @return
*/
@Select("select * from tb_brand")
List selectAll();
由于表中有些字段名和实体类中的属性名没有对应,
所以需要在 com/green/mapper/BrandMapper.xml 映射配置文件中定义结果映射 ,
使用 resultMap 标签。映射配置文件内容如下:
定义完结果映射关系后,在接口 selectAll() 方法上引用该结构映射。
使用 @ResultMap("brandResultMap") 注解完整接口的 selectAll() 方法如下:
/**
* 查询所有
* @return
*/
@Select("select * from tb_brand")
@ResultMap("brandResultMap")
List selectAll();
service方法实现
在 com.green.service 包下创建 BrandService 接口,在该接口中定义查询所有的抽象方法
public interface Brandservice {
/**
* 查询所有
* @return
*/
List selectAll();
}
并在 com.green.service 下再创建 impl 包; impl 表示是放 service 层接口的实现类的包。
在该包下创建名为BrandServiceImpl 类
public class BrandServiceImpl implements Brandservice {
@Override
public List selectAll() {
return null;
}
}
此处为什么要给 service 定义接口呢?因为service定义了接口后,
在 servlet 中就可以使用多态的形式创建Service实现类的对象,如下:
这里使用多态是因为方便我们后期解除 Servlet 和 service 的耦合。
从上面的代码可以看到 SelectAllServlet 类和 BrandServiceImpl 类之间是耦合在一起的,
如果后期 BrandService 有其它更好的实现类(例如叫BrandServiceImpl ),
那就需要修改 SelectAllServlet 类中的代码。
//BrandServiceImpl 类代码如下:
public class BrandServiceImpl implements BrandService {
//1、创建SqlSessionFactory 工厂对象
SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
@Override
public List selectAll() {
//2、获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//3、获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4、调用方法
List brands = mapper.selectAll();
//释放资源
sqlSession.close();
return brands;
}
}
servlet实现
在 com.green.web.servlet 包下定义名为 SelectAllServlet 的查询所有的 servlet 。
该 servlet 逻辑如下:
调用service的 selectAll() 方法查询所有的品牌数据,并接口返回结果
将返回的结果转换为 json 数据
响应 json 数据
@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
private BrandService brandservice = new BrandServiceImpl();//多态
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、调用service查询数据
List brands = brandservice.selectAll();
//2、转为JSON
String jsonString = JSON.toJSONString(brands, SerializerFeature.IgnoreNonFieldGetter);
//String jsonString = JSON.toJSONString(brands);
//3、写数据
response.setContentType("text/json;charset=utf-8"); //告知浏览器响应的数据是什么, 告知浏览器使用什么字符集进行解码
response.getWriter().write(jsonString);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
测试后端程序
在浏览器输入访问servlet的资源路径 http://localhost:8080/brand-case/selectAllServlet ,
如果没有报错,并能看到如下信息表明后端程序没有问题
前端实现
前端需要在页面加载完毕后发送 ajax 请求,所以发送请求的逻辑应该放在 mounted() 钩子函数中。
而响应回来的数据需要赋值给表格绑定的数据模型,从下图可以看出表格绑定的数据模型是tableData
mounted() {
//页面加载完成后,发送异步请求,获取数据
var _this = this;
axios({
method:"get",
url: "http://localhost:8080/brand-case/selectAllServlet"
}).then(function (resp) {
_this.tableData = resp.data;
})
}
Title
查询
批量删除
新增
提交
取消
修改
删除
//BrandMapper创建方法
/**
* 添加数据
* @param brand
*/
@Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")
void add(Brand brand);
//BrandServlet创建方法
/**
* 添加数据
* @param brand
*/
void add(Brand brand);
//BrandServletlmpl
@Override
public void add(Brand brand) {
//2、获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//3、获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4、调用方法
mapper.add(brand);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
servlet实现
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
private BrandService brandservice = new BrandServiceImpl();//多态
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、接收数据
// 获取请求体数据 按行读取数据
BufferedReader br = request.getReader();
String params = br.readLine();//json字符串
// 将JSON字符串转为Java对象
Brand brand = JSON.parseObject(params, Brand.class);
//2、调用brandservice添加数据
brandservice.add(brand);
//3. 响应成功标识
response.getWriter().write("success");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
前端代码实现
Title
查询
批量删除
新增
提交
取消
修改
删除
问题导入
Web 层的 Servlet 个数太多了,不利于管理和编写
通过之前的两个功能,发现每一个功能都需要定义一个 servlet ,一个模块需要实现增删改查功能,
就需要4个servlet ,模块一多就会造成 servlet 泛滥。
此时我们就想 servlet 能不能像 service 一样,一个模块只定义一个servlet ,
而每一个功能只需要在该 servlet 中定义对应的方法,例如下面的代码:
@WebServlet("/brand/*")
public class BrandServlet {
//查询所有
public void selectAll(...) {}
//添加数据
public void add(...) {}
//修改数据
public void update(...) {}
//删除删除
public void delete(...) {}
}
为了做到通用,定义一个通用的servlet类,在定义其他的servlet是不需要继承HttpServlet ,
而继承我们定义的BaseServlet,在BaseServlet中调用具体servlet(如BrandServlet)中的对应方法。
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
//进行请求的分发
}
}
//BrandServlet 定义就需要修改为如下:
@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet {
//用户实现分页查询
public void selectAll(...) {}
//添加企业信息
public void add(...) {}
//修改企业信息
public void update(...) {}
//删除企业信息
public void delete(...) {}
}
如何在 BaseServlet 中调用对应的方法呢?比如查询所有就调用 selectAll() 方法。
可以规定在发送请求时,请求资源的二级路径(/brandServlet/selectAll)和需要调用的方法名相同,
如:查询所有数据的路径以后就需要写成:http://localhost:8080/brand-case/brandServlet/selectAll
添加数据的路径以后就需要写成:http://localhost:8080/brand-case/brandServlet/add
修改数据的路径以后就需要写成:http://localhost:8080/brand-case/brandServlet/update
删除数据的路径以后就需要写成:http://localhost:8080/brand-case/brandServlet/delete
这样的话,在 BaseServlet 中就需要获取到资源的二级路径作为方法名,然后调用该方法
/**
* 替换HttpServlet,根据请求的最后一段路径进行方法分发
*/
public class BaseServlet extends HttpServlet {
//根据请求的最后一段路径进行方法分发
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、获取请求路径
String uri = req.getRequestURI(); // brand-case/brand/selectAll
//System.out.println(uri);
//2、获取最后一段路径 方法名
int index = uri.lastIndexOf('/');
String methodName = uri.substring(index + 1);
//System.out.println(methodName);
//3、执行方法
//3.1 获取BrandServlet / UserServlet 字节码对象class
//谁调用我(this 所在的方法),我(this)代表谁
//System.out.println(this);
Class extends BaseServlet> cls = this.getClass();
//3.2 获取方法Method对象
try {
Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//3.3 执行方法
try {
method.invoke(this, req, resp);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
后端优化
定义了 BaseServlet 后,针对品牌模块定义一个 BrandServlet 的 Servlet,
并使其继承 BaseServlet 。在BrandServlet 中定义 以下功能的方法:
查询所有 功能:方法名声明为selectAll ,并将之前的SelectAllServlet中的逻辑代码拷贝到该方法中
添加数据 功能:方法名声明为 add ,并将之前的 AddServlet 中的逻辑代码拷贝到该方法中
@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet {
private BrandService brandservice = new BrandServiceImpl();//多态
public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println("brand selectAll....");
//1、调用service查询数据
List brands = brandservice.selectAll();
//2、转为JSON
String jsonString = JSON.toJSONString(brands, SerializerFeature.IgnoreNonFieldGetter);
//String jsonString = JSON.toJSONString(brands);
//3、写数据
response.setContentType("text/json;charset=utf-8"); //告知浏览器响应的数据是什么, 告知浏览器使用什么字符集进行解码
response.getWriter().write(jsonString);
}
public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println("brand add....");
//1、接收数据
// 获取请求体数据 按行读取数据
BufferedReader br = request.getReader();
String params = br.readLine();//json字符串
// 将JSON字符串转为Java对象
Brand brand = JSON.parseObject(params, Brand.class);
//2、调用brandservice添加数据
brandservice.add(brand);
//3. 响应成功标识
response.getWriter().write("success");
}
}
前端优化
页面中之前发送的请求的路径都需要进行修改,
selectAll() 函数中发送异步请求的 url 应该改为
http://localhost:8080/brand-case/brand/selectAll
addBrand() 函数中发送异步请求的 url 应该改为
http://localhost:8080/brand-case/brand/add
//BrandMapper
/**
* 根据id修改数据
*
* @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);
//BrandService接口 方法
/**
* 修改数据
* @param brand
*/
void update(Brand brand);
//BrandServiceImpl 重写方法
@Override
public void update(Brand brand) {
//2、获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//3、获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4. 调用方法
mapper.update(brand);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
//BrandServlet
//修改数据
public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求体数据 按行读取数据
BufferedReader br = request.getReader();
String params = br.readLine();//json字符串
// 将JSON字符串转为Java对象
Brand brand = JSON.parseObject(params, Brand.class);
//2、调用brandservice修改数据
brandservice.update(brand);
//3. 响应成功标识
response.getWriter().write("success");
}
前端代码:
//创建一个修改数据的对话框
提交
取消
//在表格 修改 按钮 绑定一个单击事件 startEdit(scope.row) 传入的是行的数据
修改
删除
//在methods中定义方法startEdit() 和 updateBrand()
startEdit(row) {
// 获取修改行已经有的数据,以供填入修改框
var _this = this
_this.brandEdition = JSON.parse(JSON.stringify(row));
// 弹出修改框
_this.editDialogVisible = true;
},
//修改品牌
updateBrand() {
//2. 发送ajax请求
var _this = this;
axios({
method: "post",
url: "http://localhost:8080/brand-case/brand/update",
data: _this.brandEdition
}).then(function (resp) {
// 判断响应数据是否为 success 跳转brand.html
if (resp.data === "success") {
//修改成功
//关闭窗口
_this.editDialogVisible = false;
//添加成功弹窗消息
_this.$message({
message: '恭喜你,修改数据成功!',
type: 'success'
});
//重新查询产品数据
_this.selectAll();
}
})
}
//data数据区添加一个修改数据的品牌模型
//修改品牌模型数据
brandEdition: {
id: '',
brandName: '',
companyName: '',
ordered: '',
description: '',
status: ''
}
Title
查询
批量删除
新增
修改
删除
提交
取消
提交
取消
后端实现
//BrandMapper
/**
* 根据id删除数据
* @param id
*/
@Delete("delete from tb_brand where id = #{id}")
void deleteById(int id);
//BrandService接口
/**
* 删除数据
* @param id
*/
void deleteById(int id);
//BrandServiceImpl
@Override
public void deleteById(int id) {
//2、获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//3、获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4. 调用方法
mapper.deleteById(id);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
//BrandServlet
//删除数据
public void deleteById(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 参数是通过get请求获取的,不需要JSON来转换
//接收id
String sid = request.getParameter("id");
int id = Integer.parseInt(sid);
//2、调用brandservice删除数据
brandservice.deleteById(id);
//3. 响应成功标识
response.getWriter().write("success");
}
前端实现
Title
查询
批量删除
新增
修改
删除
提交
取消
提交
取消
注意:
前端发送请求时需要将要删除的多个id值以json格式提交给后端,而该json格式数据如下:
[1,2,3]
后端实现
//BrandMapper
/**
* 批量删除
* @param ids
*/
void deleteByIds(@Param("ids") int[] ids);
//BrandMapper 映射文件
delete from tb_brand where id in
#{id}
//BrandService 接口
/**
* 批量删除
* @param ids
*/
void deleteByIds(int[] ids);
//BrandServiceImpl 实现类
@Override
public void deleteByIds(int[] ids) {
//2、获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//3、获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4. 调用方法
mapper.deleteByIds(ids);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
//BrandServlet
//批量删除数据
public void deleteByIds(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求体数据 按行读取数据 [1,2,3]
BufferedReader br = request.getReader();
String params = br.readLine();//json字符串
// 将JSON字符串转为Java对象
int[] ids = JSON.parseObject(params, int[].class);
//2、调用brandservice批量删除数据
brandservice.deleteByIds(ids);
//3. 响应成功标识
response.getWriter().write("success");
}
前端实现
获取选中的id值
从上图可以看出表格复选框绑定了一个selection-change事件,该事件是当选择项发生变化时会触发。
该事件绑定了handleSelectionChange 函数,而该函数有一个参数 val ,
该参数是获取选中行的数据,如下
所有只需要将所有选中数据的id值提交给服务端即可,
在 批量删除 按钮绑定单击事件,并给绑定触发时调用的函数,如下
在Vue对象中的 methods 中定义 deleteByIds() 函数,
在该函数中从 multipleSelection 数据模型中获取所选数据的id值。
要完成这个功能需要在 Vue 对象中定义一个数据模型 selectedIds:[] ,
在 deleteByIds() 函数中遍历multipleSelection 数组,并获取到每一个所选数据的id值存储到 selectedIds 数组中,代码实现如下:
//创建id数组[1,2,3] 从this.multipleSelection 获取id
for (let i = 0; i < this.multipleSelection.length; i++) {
this.selectedIds[i] = this.multipleSelection[i].id;
}
发送异步请求
使用 axios 发送异步请求并经上一步获取到的存储所有的 id 数组作为请求参数
var _this = this
axios({
method: "post",
url: "http://localhost:8080/brand-case/brand/deleteByIds",
data:_this.selectedIds
}).then(function (resp) {
// 判断响应数据是否为 success 跳转brand.html
if (resp.data === "success") {
//删除成功弹窗消息
_this.$message({
message: '恭喜你,删除数据成功!',
type: 'success'
});
//重新查询产品数据
_this.selectAll();
}
})
})
确定框实现
由于删除操作是比较危险的;有时候可能是由于用户的误操作点击了 批量删除 按钮,
所以在点击了按钮后需要先给用户确认提示。而确认框在 elementUI 中也提供了,如下图
//批量删除数据
deleteByIds() {
console.log(this.multipleSelection);
//multipleSelection数组内容
/*[
{
"brandName": "华为",
"companyName": "华为技术有限公司",
"description": "万物互联",
"id": 1,
"ordered": 100,
"status": 1
},
{
"brandName": "小米",
"companyName": "小米科技有限公司",
"description": "are you ok",
"id": 2,
"ordered": 50,
"status": 1
},
{
"brandName": "格力",
"companyName": "格力电器股份有限公司",
"description": "让世界爱上中国造",
"id": 3,
"ordered": 30,
"status": 1
}
]*/
//创建id数组[1,2,3] 从this.multipleSelection 获取id
for (let i = 0; i < this.multipleSelection.length; i++) {
this.selectedIds[i] = this.multipleSelection[i].id;
}
//是否删除提示框
this.$confirm('是否确定删除数据?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//确认删除操作
var _this = this
axios({
method: "post",
url: "http://localhost:8080/brand-case/brand/deleteByIds",
data:_this.selectedIds
}).then(function (resp) {
// 判断响应数据是否为 success 跳转brand.html
if (resp.data === "success") {
//删除成功弹窗消息
_this.$message({
message: '恭喜你,删除数据成功!',
type: 'success'
});
//重新查询产品数据
_this.selectAll();
}
})
}).catch(() => {
//取消删除
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
-- 分页查询的SQL语句
/*查询数据*/
SELECT * FROM tb_brand;
-- 分页查询
-- 参数一 : 开始索引
-- 参数二 : 查询的条目数
select * from tb_brand limit 0,5;
select * from tb_brand limit 5,5;
-- 页面传递的参数:
-- 当前页码
-- 每页显示条数
-- 参数一 : 开始索引 = (当前页码-1)*每页显示条数
-- 参数二 : 查询的条目数 = 每页显示条数
前后端数据分析
//在 pojo 包下创建 PageBean 类,为了做到通用会将其定义成泛型类
public class PageBean {
private int totalCount;
private List rows;
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public List getRows() {
return rows;
}
public void setRows(List rows) {
this.rows = rows;
}
}
流程分析
后端需要响应 总记录数 和 当前页的数据 两部分数据给前端,
所以在 BrandMapper 接口中需要定义两个方法:
selectByPage() :查询当前页的数据的方法
selectTotalCount() :查询总记录的方法
后端实现
//在 BrandMapper 接口中定义 selectByPage() 方法进行分页查询
/**
* 分页查询
* @param begin 开始页码
* @param size 查询条目数
* @return
*/
@Select("select * from tb_brand limit #{begin } , #{size} ")
@ResultMap("brandResultMap")
List selectByPage(@Param("begin") int begin, @Param("size") int size);
//在 BrandMapper 接口中定义 selectTotalCount() 方法进行统计记录数
/**
* 查询总记录数
* @return
*/
@Select("select count(*) from tb_brand")
int selectTotalCount();
//在 BrandService 接口中定义 selectByPage() 分页查询数据的业务逻辑方法
/**
* 分页查询
* @param currentPage 当前页码
* @param pageSize 每页查询条数
* @return
*/
PageBean selectByPage(int currentPage,int pageSize);
//在 BrandServiceImpl 类中重写 selectByPage() 方法,并进行业务逻辑实现
@Override
public PageBean selectByPage(int currentPage, int pageSize) {
//2、获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//3、获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//计算开始索引
int begin = (currentPage-1)*pageSize;
//查询条目数
int size =pageSize;
//4. 调用方法 查询当前页数据
List rows = mapper.selectByPage(begin, size);
//查询总记录数
int totalCount = mapper.selectTotalCount();
//封装成PageBean对象
PageBean pageBean = new PageBean<>();
pageBean.setRows(rows);
pageBean.setTotalCount(totalCount);
//释放资源
sqlSession.close();
return pageBean;
}
在 BrandServlet 类中定义 selectByPage() 方法。而该方法的逻辑如下:
获取页面提交的 当前页码 和 每页显示条目数 两个数据。
这两个参数是在url后进行拼接的,格式是 url? currentPage=1&pageSize=5 。
获取这样的参数需要使用 requet.getparameter() 方法获取。
调用 service 的 selectByPage() 方法进行分页查询的业务逻辑处理
将查询到的数据转换为 json 格式的数据
响应 json 数据
//servlet 中 selectByPage() 方法代码实现如下:
//分页查询
public void selectByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收当前 页码 和 页码条目数 URL?currentPage=1&pageSize=5
String _currentPage = request.getParameter("currentPage");
String _pageSize = request.getParameter("pageSize");
int currentPage = Integer.parseInt(_currentPage);
int pageSize = Integer.parseInt(_pageSize);
//调用调用brandservice分页查询
PageBean pageBean = brandservice.selectByPage(currentPage, pageSize);
//2、转为JSON
String jsonString = JSON.toJSONString(pageBean, SerializerFeature.IgnoreNonFieldGetter);
//String jsonString = JSON.toJSONString(brands);
//3、写数据
response.setContentType("text/json;charset=utf-8"); //告知浏览器响应的数据是什么, 告知浏览器使用什么字符集进行解码
response.getWriter().write(jsonString);
}
前端实现
Title
查询
批量删除
新增
修改
删除
提交
取消
提交
取消
3个条件之间什么关系?
同时满足,所用 SQL 中多个条件需要使用 and 关键字连接
3个条件必须全部填写吗?
不需要。想根据哪儿个条件查询就写那个,所以这里需要使用动态 sql 语句
条件查询需要分页吗?
需要
根据上面三个问题的明确,就可以确定sql语句了
后端实现
//在 BrandMapper 接口中定义 selectByPageAndCondition() 方法
//和 selectTotalCountByCondition 方法,用来进行条件分页查询功能
/**
* 条件分页查询
* @param begin 开始页码
* @param size 查询条目数
* @param brand 封装条件的brand对象
* @return
*/
List selectByPageAndCondition(@Param("begin") int begin, @Param("size") int size, @Param("brand") Brand brand);
/**
* 条件查询总记录数
* @return
*/
int selectTotalCountByCondition(Brand brand);
//在映射配置文件中书写 sql 语句。 brand_name 字段和company_name 字段需要进行模糊查询,
//所以需要使用 % 占位符。映射配置文件中 statement 书写如下:
//在 BrandService 接口中定义 selectByPageAndCondition() 分页查询数据的业务逻辑方法
/**
* 根据条件分页查询
* @param currentPage
* @param pageSize
* @param brand
* @return
*/
PageBean selectByPageAndCondition(int currentPage,int pageSize,Brand brand);
//在 BrandServiceImpl 类中重写 selectByPageAndCondition() 方法,并进行业务逻辑实现
@Override
public PageBean selectByPageAndCondition(int currentPage, int pageSize, Brand brand) {
//2、获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//3、获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//计算开始索引
int begin = (currentPage - 1) * pageSize;
//查询条目数
int size = pageSize;
//处理brand的条件 模糊表达式 模糊查询
String brandName = brand.getBrandName();
String companyName = brand.getCompanyName();
if (brandName != null && brandName.length() > 0) {
brand.setBrandName("%" + brandName + "%");
}
if (companyName != null && companyName.length() > 0) {
brand.setCompanyName("%" + companyName + "%");
}
//4. 调用方法 条件查询当前页数据
List rows = mapper.selectByPageAndCondition(begin, size, brand);
//条件查询总记录数
int totalCount = mapper.selectTotalCountByCondition(brand);
//封装成PageBean对象
PageBean pageBean = new PageBean<>();
pageBean.setRows(rows);
pageBean.setTotalCount(totalCount);
//释放资源
sqlSession.close();
return pageBean;
}
注意:brandName和companyName 属性值到时候需要进行模糊查询,所以前后需要拼接上 %
//在 BrandServlet 类中定义 selectByPageAndCondition() 方法。而该方法的逻辑如下:
//条件分页查询
public void selectByPageAndCondition(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收当前 页码 和 页码条目数 URL?currentPage=1&pageSize=5
String _currentPage = request.getParameter("currentPage");
String _pageSize = request.getParameter("pageSize");
int currentPage = Integer.parseInt(_currentPage);
int pageSize = Integer.parseInt(_pageSize);
// 获取请求体数据 按行读取数据
BufferedReader br = request.getReader();
String params = br.readLine();//json字符串
// 将JSON字符串转为Java对象
Brand brand = JSON.parseObject(params, Brand.class);
//调用调用brandservice 条件分页查询
PageBean pageBean = brandservice.selectByPageAndCondition(currentPage, pageSize,brand);
//2、转为JSON
//String jsonString = JSON.toJSONString(pageBean, SerializerFeature.IgnoreNonFieldGetter);
String jsonString = JSON.toJSONString(pageBean);
//3、写数据
response.setContentType("text/json;charset=utf-8"); //告知浏览器响应的数据是什么, 告知浏览器使用什么字符集进行解码
response.getWriter().write(jsonString);
}
前端实现
Title
查询
批量删除
新增
修改
删除
提交
取消
提交
取消