存在问题:如果学生数量很多,查询起来就很费力,这时候就要提供查询功能,使用动态sql语句了。
一·在网页上添加组合查询区
1·略作修改看看效果
来到list_student.jsp:
在如下位置添加:
注意检查蓝色方框的标签是否存在,没有的话会导致,列表变宽。
<!-- 组合查询区 -->
<div class="row">
<div class="col-12"><!-- col-12是占满一行 -->
<div id="queryArea">
<!-- 测试一下 -->
fhvusdhvjsfbvjhdfbvhjdfbvjdfbvjfd
</div>
</div>
</div>
2·进一步修改,准备使表单排在一行上
添加:
<div class="from-row"><!-- from-row:表单是排在一行上面的 -->
</div>
原来没有写是一行一行排。
3·添加查询使用的姓名输入框
<div class="form-group col-3">
<input type="text" class="form-control" name="qryStuName">
</div>
位置如下:
效果:
使用占位器,来显示提示:
通过查阅bootStrap文档,https://getbootstrap.com/docs/4.5/components/forms/?:
修改:
<div class="form-group col-3">
<input type="text" class="form-control" name="qryStuName" placeholder="请输入学生姓名(模糊适配)">
</div>
效果:
4·添加查询分数段的输入框
修改:
<!-- form-row:表单是排在一行上面的 -->
<div class="form-group col-3">
<input type="text" class="form-control" name="qryStuName"
placeholder="请输入学生姓名(模糊适配)">
</div>
<label class="col-form-label">分数段:</label>
<div class="form-group col-1">
<input type="text" class="form-control" name="qryBeginMark">
</div>
-
<div class="form-group col-1">
<input type="text" class="form-control" name="qryEndMaark">
</div>
效果:
5·添加查询按钮
<div class="form-group col-md-3">
<button class="btn btn-primary"> 查 询 </button>
</div>
效果:
二·实现查询
我们默认的查询时没有任何条件的查询,是正常(有条件)查询的一种特殊形式。
1·添加一个查询助手类
来到Service包,新建StudentQryHelper类,用以封装查询数据,
private String qryStuName;
private Double qryBeginMark;
private Double qryEndMark;
不是domain,所以放在Service这边,再添加Getter和Setter:
原来Service的loadStus()是没有任何条件的:
现在增加一个带条件的:
在StudentService添加:
List<Student> loadStus(StudentQryHelper helper);
这是方法的重载,如果helper里面没有任何数据,就是查询所有。所以,原来的那个loadStus()可以没有,
来到StudentDao:
List<Student> loadStusByCondition(StudentQryHelper helper);
暂时不覆盖掉原来的方法。
来到StudentMapper:
返回类型以为helper没有放在domain里面所以是没有办法做默认。
查询还是那个查询,但是是有条件的
查看Mybatis文档:https://mybatis.org/mybatis-3/zh/dynamic-sql.html
在StudentMapper中添加:
<select id="loadStusByCondition" parameterType="edu.mju.stuwork.service.StudentQryHelper" resultType="Student">
select *
from tbl_student where 1=1
<if test="qryStuName != null">
and stu_name like #{qryStuName}
</if>
<if test="qryBeginMark != null">
and stu_mark >= #{qryBeginMark}
</if>
<if test="qryEndMark != null">
and stu_mark <= #{qryEndMark}
</if>
order by stu_no desc
</select>
说明如下:
where 1=1,是为了占掉第一个条件,剩下的都是第二个条件。
“<”要使用转义符,参照Mybatis中动态sql的条件为 小于等于 或大于等于的时候写小于号报错,使用“<”代替。
来到StudentController:
修改loadStus:
@GetMapping("/students")
public String loadStus(Model model,StudentQryHelper helper) throws Exception {
//为了支持模糊查询
if(helper.getQryStuName()!=null)
helper.setQryStuName("%"+helper.getQryStuName()+"%");
List<Student> stuList = stuService.loadStus(helper);
以key/value键值对形式保存到模型,其实就是保存到request范围(请求范围)
model.addAttribute("stuList", stuList);
return "list_student";// 去到页面,叫list_student
}
来到StudentServiceImpl:
实现带参数的loadStus();
@Override
public List<Student> loadStus(StudentQryHelper helper) {
return stuDao.loadStusByCondition(helper);
}
如果helper为空,就是在映射中:
这些条件都不成立,就和原来的loadStus()是一样的了。
查询按钮还没有表单,所以按钮还不能用。
来到list_student.jsp:
修改,添加:
<form action="<c:url value="/students"/>" method="get">
</form>
测试:
调整log4j,为debug为了看到sql的变化。
动态sql:
再模糊查询:
三·稍作修改
1·在list_student添加:
<label class="col-form-label">学生姓名:</label>
四·存在的问题
1·空串问题
来到:
查询成绩是676的学生。回到控制台可以看到:
虽然我们在“学生姓名”查询框中并没有填写内容,但是在服务器端却以空串的形式进行了查询。
在debug模式下可以看到:
其确实是以空串的形式读入。
解决方法:
在StudentController:
添加:
if (org.apache.commons.lang3.StringUtils.isBlank(helper.getQryStuName())) {//使用lang3包的方法,做一个空串的检测
helper.setQryStuName(null);//使空串成为null,使下面的模糊查询不加上“%”,并使StudentMapper的动态sql语句不再添加相关部分的语句。
}
位置如下:
2·"where 1=1"干扰了数据库对sql语句执行的流程
解决方法:
来到“StudentMapper”对“loadStusByCondition”做修改:
原来:
现在:
<select id="loadStusByCondition" parameterType="edu.mju.stuwork.service.StudentQryHelper" resultType="Student">
select *
from tbl_student
<trim prefix="WHERE " prefixOverrides="AND |OR "><!-- 如果下面的if判断是有东西的,会自动在前面加上where。如果底下的if里有and,且是第一个,就把and拿掉 -->
<if test="qryStuName != null">
and stu_name like #{qryStuName}
</if>
<if test="qryBeginMark != null">
and stu_mark >= #{qryBeginMark}
</if>
<if test="qryEndMark != null">
and stu_mark <= #{qryEndMark}
</if>
</trim>
order by stu_no desc
</select>
3·用户在查询之后,查询条件就消失了,不知道原来查的啥
要将查询条件回填。
来到StudentController:
添加:
model.addAttribute("helper",helper);
到:
来到list_student.jsp,使用EL表达式回填:
测试:
重新部署之后session就被摧毁了,所以要重新登入。
4·当查询结果是空时,列表是空白
但是当查询结果是空时,列表是空白。应该显示:“没有符合查询条件的学生”之类的。
来到list_student:
修改:
当stuList不为空时,才显示,数据表格。当stuList为空时,显示提示信息。
测试:
来到https://getbootstrap.com/docs/5.0/components/alerts/,找一个alter。
添加:
<div class="alert alert-primary" role="alert">
没有符合查询条件的学生信息被找到!
</div>
位置:
效果:
再调试一下:
<c:if test="${empty stuList }">
<div class="alert alert-primary col-6 text-center py-5 mt-5 offset-md-3" role="alert">
没有符合查询条件的学生信息被找到!
</div>
</c:if>
col-6:占50%
py-5:保持5个单位的padding
offset-md-3:左边越过3个单位
text-center:文字居中
效果:
通过h3,调节一下文字大小:
5·还有回填值时的%问题
参考:http://baijiahao.baidu.com/s?id=1654523881624000395&wfr=spider&for=pc
修改:
为:
来到StudentMapper:
<select id="loadStusByCondition" parameterType="edu.mju.stuwork.service.StudentQryHelper" resultType="Student">
select *
from tbl_student
<trim prefix="WHERE " prefixOverrides="AND |OR "><!-- 如果下面的if判断是有东西的,会自动在前面加上where。如果底下的if里有and,且是第一个,就把and拿掉 -->
<if test="qryStuName != null">
and stu_name like concat('%','${qryStuName}','%')
</if>
<if test="qryBeginMark != null">
and stu_mark >= #{qryBeginMark}
</if>
<if test="qryEndMark != null">
and stu_mark <= #{qryEndMark}
</if>
</trim>
order by stu_no desc
</select>
查询“天”
“?”占位天。
用$就是把字符串直接放进去不是变成“?”:
来到StudentController:
这个部分就可以删掉了:
测试: