增强,添加一些东西
一·学生性别
1·数据库
在数据库中添加字段“学生性别”,char(1),男就是“M”,女就是“F”,允许空。
alter table tbl_student add stu_sex char(1);
2·添加Student的属性
添加Getter和Setter
3·界面
需要一个单选框
3·1·来找两个横着的单选:
3·2·在list_student的新生注册模态窗,修改:
添加:form-group,再加上“学生性别”,然后,把刚刚复制的贴上去。
效果:
再做修改:
3·3·改成“男”,“女”,多余的按钮去掉。radio使用同样的名字可以实现互斥。
radio使用同样的名字,会形成一个组,可以实现互斥。
去掉ID,再修改radio的name为“stuSex”,使其与Student的属性名一致,否则传不进去,设置value,男是M,女是F:
3·4·设置默认值
如果这个学校女女生比较多,每次都要点一下就比较麻烦。
将其设为默认值:
3·5·代码
<div class="form-group">
<label>学生性别:</label>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio"
name="stuSex" value="M">
<label class="form-check-label" for="inlineRadio1">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio"
name="stuSex" value="F" checked="checked">
<label class="form-check-label" for="inlineRadio2">女</label>
</div>
</div>
二·学生籍贯
1·数据库
在数据库中添加字段“学生籍贯”,char(2),福州就是“FZ”,南平就是“NP”,允许空。
alter table tbl_student add stu_origin char(2);
2·添加Student的属性
添加Getter和Setter
3·界面
需要一个下拉选
在list_student添加:
<div class="form-group">
<label>学生籍贯</label><br>
<select class="form-select" aria-label="Default select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
效果:
再做修改,预设为“请选择”,如果没有“请选择”这一行,默认就是选项的第一条。比如“南平”,但是这样往往会使用户忘记选择。设置“请选择”,可以设置检验,如果在提交表单时,没有选,就会提示。将form-select改为form-control,提交时的名字设为“stuOrigin”:
<div class="form-group">
<label>学生籍贯</label><br>
<select class="form-control" name="stuOrigin" aria-label="Default select example">
<option selected>--请选择--</option>
<option value="NP">南平</option>
<option value="FZ">福州</option>
<option value="QZ">泉州</option>
<option value="XM">厦门</option>
</select>
</div>
这样写可以添加默认值:
但是我们就不添加了。
三·性别和籍贯数据落地
1·保存
来到StudentMapper:
添加:,做全字段更新:
查询数据库的情况:
select stu_no,stu_name,stu_mark,stu_sex,stu_origin from tbl_student order by stu_no desc;
tips:TypeScript:将正常语言转换为js
webpark:打包工具
flutter
2·显示数据
来到list_student:
添加:
<th scope="col">性别</th>
<th scope="col">籍贯</th>
添加:
<td>${stu.stuSex}</td>
<td>${stu.stuOrigin}</td>
3·将“F”和“NP”进行转换
来到list_student:
添加:
<td>
<c:if test="${stu.stuSex=='M'}">男</c:if>
<c:if test="${stu.stuSex=='F'}">女</c:if>
</td>
<td>
<c:choose>
<c:when test="${stu.stuOrigin=='FZ'}">福州</c:when>
<c:when test="${stu.stuOrigin=='QZ'}">泉州</c:when>
<c:when test="${stu.stuOrigin=='XM'}">厦门</c:when>
<c:when test="${stu.stuOrigin=='NP'}">南平</c:when>
<c:otherwise>---</c:otherwise>
</c:choose>
</td>
c:choose相当于switch,case,多分枝选择。<c:otherwise>类似于default。
测试:
删除还是没有影响的,但是修改界面还不支持。
四·实现性别和籍贯的修改
来到update_student.jsp:
添加从list_student复制来的:
<div class="form-group">
<label>学生性别:</label>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="stuSex"
value="M"> <label class="form-check-label"
for="inlineRadio1">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="stuSex"
value="F" checked="checked"> <label
class="form-check-label" for="inlineRadio2">女</label>
</div>
</div>
到:
效果:
在update_student.jsp添加从list_student复制来的:
<div class="form-group">
<label>学生籍贯</label><br> <select class="form-control"
name="stuOrigin" aria-label="Default select example">
<option selected>--请选择--</option>
<option value="NP">南平</option>
<option value="FZ">福州</option>
<option value="QZ">泉州</option>
<option value="XM">厦门</option>
</select>
</div>
效果:
1·数据回填
这两个的回填就是看那个要写checked了:
1·1·学生性别回填
<div class="form-group">
<label>学生性别:</label>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="stuSex"
value="M" <c:if test="${stu.stuSex=='M'}">checked</c:if>>
<label class="form-check-label" for="inlineRadio1">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="stuSex"
value="F" <c:if test="${stu.stuSex=='F'}">checked</c:if>>
<label class="form-check-label" for="inlineRadio2">女</label>
</div>
</div>
1·2·学生籍贯回填
修改:
<div class="form-group">
<label>学生籍贯</label><br> <select class="form-control"
name="stuOrigin" aria-label="Default select example">
<option selected>--请选择--</option>
<option value="NP"
<c:if test="${stu.stuOrigin=='NP'}">selected</c:if>>南平</option>
<option value="FZ"
<c:if test="${stu.stuOrigin=='FZ'}">selected</c:if>>福州</option>
<option value="QZ"
<c:if test="${stu.stuOrigin=='QZ'}">selected</c:if>>泉州</option>
<option value="XM"
<c:if test="${stu.stuOrigin=='XM'}">selected</c:if>>厦门</option>
</select>
</div>
1·3·测试
2·修改的数据落地
2·1·StudentMapper
来到StudentMapper:
修改:updateStudent
<update id="updateStudent" parameterType="Student">
update tbl_student
set
stu_name=#{stuName},stu_mark=#{stuMark},stu_pic=#{stuPic},stu_sex=#{stuSex},stu_origin=#{stuOrigin}
where
stu_no=#{stuNo}
</update>
2·2·测试
对于老数据也可以更新:
3·在数据库更新
为了准备下面的过滤,执行数据库级别的更新:
3·1·性别全部设为女:
update tbl_student set stu_sex='M' where stu_sex is null;
select stu_no,stu_name,stu_mark,stu_sex,stu_origin from tbl_student order by stu_no desc;
3·2·全部纳入福州管理
update tbl_student set stu_origin='FZ' where stu_origin is null;
select stu_no,stu_name,stu_mark,stu_sex,stu_origin from tbl_student order by stu_no desc;
五·添加新的过滤条件
1·在StudentQryHelper添加两个条件用于接收
再添加Getter和Setter。
2·在list_student的查询区添加对应组件
添加:
<div class="form-group col-2">
<select class="form-control" name="qrySex">
<option value="">--选择性别--</option>
<option value="M">男</option>
<option value="F">女</option>
</select>
</div>
<div class="form-group col-2">
<select class="form-control" name="qryOrigin">
<option value="">--选择籍贯--</option>
<option value="NP">南平</option>
<option value="FZ">福州</option>
<option value="QZ">泉州</option>
<option value="XM">厦门</option>
</select>
</div>
为了使“查询”按钮排在一行,修改为:
效果:
3·在StudentMapper做更新
qrySex不为空,且不为空值。
3·1·在loadStusByCondition
添加:
<if test="qrySex!= null and qrySex.length()>0">
and stu_sex = #{qrySex}
</if>
<if test="qryOrigin!= null and qryOrigin.length()>0">
and stu_origin = #{qryOrigin}
</if>
位置:
3·2·在loadScopedStusByCondition
添加:
<if test="helper.qrySex!= null and helper.qrySex.length()>0">
and stu_sex = #{helper.qrySex}
</if>
<if test="helper.qryOrigin!= null and helper.qryOrigin.length()>0">
and stu_origin = #{helper.qryOrigin}
</if>
3·3·在cntStusByCondition
修改:
<if test="qrySex!= null and qrySex.length()>0">
and stu_sex = #{qrySex}
</if>
<if test="qryOrigin!= null and qryOrigin.length()>0">
and stu_origin = #{qryOrigin}
</if>
测试:
4·回填查询条件
修改list_student:
<div class="form-group col-2 ">
<select class="form-control" name="qrySex">
<option value="">--选择性别--</option>
<option value="M" <c:if test="${helper.qrySex=='M'}">selected</c:if>>男</option>
<option value="F" <c:if test="${helper.qrySex=='F'}">selected</c:if>>女</option>
</select>
</div>
<div class="form-group col-2">
<select class="form-control" name="qryOrigin">
<option value="">--选择籍贯--</option>
<option value="NP" <c:if test="${helper.qryOrigin=='NP'}">selected</c:if>>南平</option>
<option value="FZ" <c:if test="${helper.qryOrigin=='FZ'}">selected</c:if>>福州</option>
<option value="QZ" <c:if test="${helper.qryOrigin=='QZ'}">selected</c:if>>泉州</option>
<option value="XM" <c:if test="${helper.qryOrigin=='XM'}">selected</c:if>>厦门</option>
</select>
</div>
测试:
四·学生爱好
1·修改一下网页部分
做两个默认值:
效果:
添加:
<div class="form-group">
<label>学生爱好</label><br>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuhobby"
value="RD" checked> <label class="form-check-label">阅读</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuhobby"
value="RN"> <label class="form-check-label">跑步</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuhobby"
value="SW" checked> <label class="form-check-label">游泳</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuhobby"
value="CM"> <label class="form-check-label">爬山</label>
</div>
</div>
给Mybatis设计一个装换器,我们原来把blob类型装换为字节数值,因为这是常见的应用,所以Mybatis个我们提供了一个装换器。但是我们自定的多选框形成的数组存到数据库的话Mybatis并不知道该该怎么办。所以需要我们自定一个装换器。
2·修改Student,添加stuHobby实例变量
多选框一般使用字符串数组
来到Student:
添加:
private String[] stuHobby;//爱好
并添加Getter和Setter。
3·检查界面
来到界面上查看名称设好了没有。
来到list_student:
可以看到名称和Student的实例变量名不匹配。
修改“stuhobby”为“stuHobby”:
<div class="form-group">
<label>学生爱好</label><br>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuHobby"
value="RD" checked> <label class="form-check-label">阅读</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuHobby"
value="RN"> <label class="form-check-label">跑步</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuHobby"
value="SW" checked> <label class="form-check-label">游泳</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuHobby"
value="CM"> <label class="form-check-label">爬山</label>
</div>
</div>
4·测试能不能收到数据
4·1·在Student添加toString()
使用format修改原先的toString,生成后大致如下:
@Override
public String toString() {
return "Student [stuNo=" + stuNo + ", stuName=" + stuName + ", stuMark=" + stuMark + ", stuPic="
+ Arrays.toString(stuPic) + ", stuSex=" + stuSex + ", stuOrigin=" + stuOrigin + ", stuHobby="
+ Arrays.toString(stuHobby) + "]";
}
这里有Arrays.toString(stuHobby),可以吧里面的东西都读取出来。
4·2·在StudentController添加打印
4·3·测试多选框能不能保存在字符串数组中
刷新系统必然要重新登入,应为在session范围内的数据已经没有了。
新生登记:
5·将数据保存到数据库
5·1·为数据库添加相应的字段
alter table tbl_student add stu_hobby varchar(30);
将学生的爱好批量更新为阅读和爬山,以“|”来间隔:
update tbl_student set stu_hobby='RD|CM';
select stu_no,stu_name,stu_mark,stu_sex,stu_origin,stu_hobby from tbl_student;
多选框在domain中保存为一个数组,在数据库中保存为一个以“|”间隔的字符串。Mybatis做不到,要自己生成一个类型装换器。
5·2·定义装换器
5·2·1·新建包“edu.mju.stuwork.handler”,新建类“StringArrayTypeHandler”
5·2·2·使“StringArrayTypeHandler”继承“BaseTypeHandler<String[]>”
“BaseTypeHandler<String[]>”是一个泛型接口,一个抽象类,是Mybatis的基本类型装换器。
package edu.mju.stuwork.handler;
import org.apache.ibatis.type.BaseTypeHandler;
public class StringArrayTypeHandler extends BaseTypeHandler<String[]>{
}
5·2·3·实现其中的若干个抽象方法
5·2·4·StringArrayTypeHandler概述
“StringArrayTypeHandler”是我们的定义的字符串数组类型装换器,其功能是数据库里的varchar要转成字符串数组,同时要把字符串数组转成varchar的用“|”拼接的形态。
5·2·5·setNonNullParameter,把字符串数组变成字符串对应的字段
修改参数“parameter”,参数名为“stringArray”:
大致情况:得到一个字符串数组“stringArray”,将他封装成一个字符串,之后将他设到PreparedStatement里,i是第几个参数,他自己会传进来。
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String[] stringArray, JdbcType jdbcType)
throws SQLException {
//创建一个StringBuffer
StringBuffer sb = new StringBuffer();
for (String str:stringArray) {
sb.append(str).append("|");//装换为使用“|”分割的形式
}
if (sb.length()>0 ) {//当sb有值,就把最后的“|”删掉一下。
sb.deleteCharAt(sb.length()-1);
}
// 将他设到PreparedStatement里
ps.setString(i, sb.toString());
}
5·2·6·取值的三种情况,三种版本
取出来:
字段名版本
索引值版本
Callable版本
5·2·7·getNullableResult(字段名版本),把数据库里面的东西取出来,转成字符串数组
@Override
public String[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
//拿着“columnName”这个字段名,从数据库里取出来。得到的是一个字符串
String data = rs.getString(columnName);
if (data != null && data.length()>0) {//如果有东西
return data.split("\\|");//返回data,以“|”切割的形式
}
return null;
}
下面两个是这个的修改,大同小异。
5·2·8·getNullableResult(索引值版本)
@Override
public String[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String data = rs.getString(columnIndex);
if (data != null && data.length()>0) {//如果有东西
return data.split("\\|");//返回data,以“|”切割的形式
}
return null;
}
5·2·9·getNullableResult(Callable版本)
@Override
public String[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String data = cs.getString(columnIndex);
if (data != null && data.length()>0) {//如果有东西
return data.split("\\|");//返回data,以“|”切割的形式
}
return null;
}
5·2·10·完整StringArrayTypeHandler
package edu.mju.stuwork.handler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
public class StringArrayTypeHandler extends BaseTypeHandler<String[]>{
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String[] stringArray, JdbcType jdbcType)
throws SQLException {
//创建一个StringBuffer
StringBuffer sb = new StringBuffer();
for (String str:stringArray) {
sb.append(str).append("|");//装换为使用“|”分割的形式
}
if (sb.length()>0 ) {//当sb有值,就把最后的“|”删掉一下。
sb.deleteCharAt(sb.length()-1);
}
// 将他设到PreparedStatement里
ps.setString(i, sb.toString());
}
@Override
public String[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
//拿着“columnName”这个字段名,从数据库里取出来。得到的是一个字符串
String data = rs.getString(columnName);
if (data != null && data.length()>0) {//如果有东西
return data.split("\\|");//返回data,以“|”切割的形式
}
return null;
}
@Override
public String[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String data = rs.getString(columnIndex);
if (data != null && data.length()>0) {//如果有东西
return data.split("\\|");//返回data,以“|”切割的形式
}
return null;
}
@Override
public String[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String data = cs.getString(columnIndex);
if (data != null && data.length()>0) {//如果有东西
return data.split("\\|");//返回data,以“|”切割的形式
}
return null;
}
}
5·3·将这个转换器用上
5·3·1·来到StudentMapper
写上转换器,进来是一个字符串数组,用这个装换器来转。
修改,在stuHobby后添加转换器:
<!-- 映射条目,这个条目的类似是增加操作 -->
<insert id="addStu" parameterType="Student"><!-- 为了防止重名,为映射条目添加命名空间:edu.mju.stuwork.StudentMapper.addStudent --><!-- parameterType:要告诉他会传一个参数(对象)给他,对象的类型是什么 -->
insert into tbl_student
values(#{stuNo},#{stuName},#{stuMark},#{stuPic},#{stuSex},#{stuOrigin},#{stuHobby,typeHandler = edu.mju.stuwork.handler.StringArrayTypeHandler})
</insert>
5·3·2·测试:
转换器会将字符串数组转成这样一个拼接结构之后,帮助生成一个“PreparedStatement”的set方法。
6·将数据从数据库取出
6·1·来到StudentMapper
6·1·1·添加resultMap
最终生成的类型是学生类型,类型就不要写完全路径了。
id就叫StudentMap
原来resultMap返回的是一个Map现在返回的是一个学生:
原来:
id 主键,剩下就是普通字段了。
字段叫stu_hobby,属性叫stuHobby,接下来要定制转换器
原来像stu_no,stu_sex这样的都是自动的,现在多了一个stu_hobby,需要手动写了。
新增的resultMap如下:
<resultMap type="Student" id="studentMap">
<id column="stu_no" property="stuNo" />
<result column="stu_sex" property="stuSex" />
<result column="stu_name" property="stuName" />
<result column="stu_mark" property="stuMark" />
<result column="stu_origin" property="stuOrigin" />
<result column="stu_hobby" property="stuHobby"
typeHandler="org.apache.ibatis.type.BlobTypeHandler" />
</resultMap>
6·1·2·修改映射getStuByNo
将返回类型由Student类,变为自定的StudentMap
6·1·3·修改映射loadScopedStusByCondition
6·1·4修改映射loadStusByCondition
6·1·4修改映射loadStus
6·2·测试
6·2·1·设置断点
爱好取出来了,但是他没有在页面显示出来。
7·在页面呈现爱好
7·1·来到list_student
在表头籍贯之后添加爱好:
在表项添加爱好:
<td>
<c:forEach var="hobby" items="${stu.stuHobby}">
${hobby},
</c:forEach>
</td>
7·2·测试
爱好出来了,但是怎么写用户怎么知道是什么爱好。
7·3·在表项的中做判断
替换上面用的${hobby},
<c:choose>
<c:when test="${hobby=='RD'}">阅读 </c:when>
<c:when test="${hobby=='CM'}">爬山 </c:when>
<c:when test="${hobby=='SW'}">游泳 </c:when>
<c:when test="${hobby=='RN'}">跑步 </c:when>
</c:choose>
7·4·测试爱好替换
测试新增:
8·爱好修改
8·1·爱好回填
修改只回填了性别和籍贯
就是在后面放下一个chacked:
这个是固定的,但是我们是要做判断的。
springmvc有标签能实现回填,但是先不用。
<div class="form-group">
<label>学生爱好</label><br>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuHobby" value="RD"
<c:forEach var="hobby" items="${stu.stuHobby}">
<c:if test="${hobby=='RD'}"> checked</c:if>
</c:forEach>
>
<label class="form-check-label">阅读</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuHobby" value="RN"
<c:forEach var="hobby" items="${stu.stuHobby}">
<c:if test="${hobby=='RN'}"> checked</c:if>
</c:forEach>
>
<label class="form-check-label">跑步</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuHobby" value="SW"
<c:forEach var="hobby" items="${stu.stuHobby}">
<c:if test="${hobby=='SW'}"> checked</c:if>
</c:forEach>
>
<label class="form-check-label">游泳</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="stuHobby" value="CM"
<c:forEach var="hobby" items="${stu.stuHobby}">
<c:if test="${hobby=='CM'}"> checked</c:if>
</c:forEach>
>
<label class="form-check-label">爬山</label>
</div>
</div>
8·2·回填测试
8·3·实现修改
8·3·1·修改StudentMapper
添加一个字段:
<update id="updateStudent" parameterType="Student">
update tbl_student
set
stu_name=#{stuName},stu_mark=#{stuMark},stu_pic=#{stuPic},stu_sex=#{stuSex},stu_origin=#{stuOrigin},stu_hobby=#{stuHobby,typeHandler=edu.mju.stuwork.handler.StringArrayTypeHandler}
where
stu_no=#{stuNo}
</update>
8·3·2·测试