修改操作
列表操作作为一个中间的环节,起到了承上启下的关键作用。当新增操作完成之后,需要显示新增完成之后的所有数据,而到了展示数据这一个层次,可以说他能够做到很多的操作,比如上一篇的删除操作,更新上下架状态,以及图片的下载操作等等操作,而作为增删改查的另一个操作修改操作,需要操作者手动的选择某一条数据进行修改操作,这里的中转当然也要从列表进行过渡。
修改操作首先要根据要修改的商品ID查询出唯一的商品数据,然后还需要将该数据在页面中进行回填操作,而这也是练习中的一个重要环节,比如下拉框如何在生成的过程中确定应该选那一条数据,又或者单选框和复选框又该如何动态的选定该选的数据。当然,回填操作之后,就是进行数据的修改操作,修改操作本身与新增操作是非常相似的,只不过,修改操作不需要使用用户ID来判断,并且也不需要更新用户的ID信息。只需要根据修改的图书ID即可进行更新操作
1、在IBookDAO.java接口中扩充新的方法
//修改操作
public void doUpdate(Book vo);
//根据Book对象中的图书ID查询并返回对应的Book信息
public Book findById(Book vo);
2、在book-mapper.xml文件中实现对应的操作方法
<select id="findById" resultType="Book" parameterType="Book">
SELECT <include refid="bookColumns"/>,
<include refid="bookTypeColumns"/>,
<include refid="bookPressColumns"/>,
<include refid="userColumns"/>,
<include refid="proColumns"/>,
<include refid="cityColumns"/>
FROM p_book p,p_booktype t,p_bookpress s,t_user u,p_area a,p_area m
WHERE p.book_type_id=t.type_id
AND p.book_press_id=s.press_id
AND p.author_proid=a.area_id
AND p.author_cityid = m.area_id
AND p.user_id = u.userid
AND p.book_id = #{bookId}
</select>
<update id="doUpdate" parameterType="Book">
UPDATE p_book p SET p.book_name=#{bookName},p.book_author =#{bookAuthor},p.book_cover =#{bookCover},
p.book_price=#{bookPrice},p.book_type_id =#{bookTypeId},p.book_press_id =#{bookPressId},p.book_status =#{bookStatus},p.book_add_time=to_date(#{bookAddTime},'yyyy-MM-dd'),
p.book_label=#{bookLabel},p.book_desc =#{bookDesc},p.author_proid =#{authorProId},p.author_cityid =#{authorCityId}
WHERE p.book_id=#{bookId}
</update>
此处需要说明的地方,在mybatis中有取出参数中的内容:
·参数为实体类:
|-“#{}”:这种取值模式,类似于PreparedStatement中的预编译之后动态赋值的模式,但是需要做好相应的日期转换
|-“${}”:这种取值模式,是将属性中的数据直接取出来放到对应之中,如果属性中的值为字符串,取出来之后不会自动添加双引号。
·参数为基本类型(int,double),包装类,又或者集合等
|-“#{}”:这种形式下,不需要在配置文件中标明具体的名称,也即是括号中的内容可以是随意的,因为只有一个参数。而这种情况下,如果使用了“${}”方式来进行取值,则会报错。
3、在业务层IBookService.java接口中扩充方法,并且在BookServiceImpl.java类中进行实现
//调用DAO中的doUpdate()方法
public void edit(Book vo);
//调用DAO中的findById()方法
public Book editPre(Book vo);
@Override
public void edit(Book vo) {
this.bookDAO.doUpdate(vo);
}
@Override
public Book editPre(Book vo) {
return this.bookDAO.findById(vo);
}
4、在控制层BookController.java类中扩充新的方法
@RequestMapping("editPre")
public String editPre(ModelMap mmap,Book vo){
mmap.addAttribute("vo",this.bookService.editPre(vo));
return "book/updatePre";
}
@RequestMapping("edit")
@ResponseBody
public String edit(Book vo){
this.bookService.edit(vo);
return "{}";
}
修改操作与新增操作类似,都是使用ajax进行异步加载,所以此处需要加上"@ReponseBody"注解,将方法中返回的结果转换相关的格式,然后返回给ajax中的success所对应的函数中。而在editPre()方法中,使用了Book对象来接受用户选择的图书的ID信息,然后还需要将查询出来的数据带到对应的修改页面,所以还需要加一个“ModelMap”对象,将查询出来的值带到相关的页面中。
5、创建updatePre.ftl文件,并且进行数据的回填配置
<#assign base=request.contextPath />
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="${base}/plugins/layui/css/layui.css">
<link rel="stylesheet" href="${base}/plugins/layui/css/modules/layer/default/layer.css">
</head>
<body>
<form id="edit_book_form">
<input type="hidden" id="edit_book_cover" name="bookCover" value="${vo.bookCover}">
<input type="hidden" name="bookId" value="${vo.bookId}">
<table border="1">
<tr>
<td>书籍名称</td>
<td>
<input name="bookName" value="${vo.bookName}">
</td>
</tr>
<tr>
<td>书籍作者</td>
<td>
<input name="bookAuthor" value="${vo.bookAuthor}">
</td>
</tr>
<tr>
<td>书籍封面</td>
<td>
<button type="button" class="layui-btn" id="uploadPic">
<i class="layui-icon"></i>上传头像
</button>
</td>
</tr>
<tr>
<td> 预览图:</td>
<td>
<blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
<div class="layui-upload-list" id="demo1">
<p id="demoText"></p>
<img height="80px" src="${base}${vo.bookCover!}">
</div>
</blockquote>
</td>
</tr>
<tr>
<td>书籍价格</td>
<td>
<input name="bookPrice" value="${vo.bookPrice}">
</td>
</tr>
<tr>
<td>书籍类型</td>
<td>
<select id="bookTypeId" name="bookTypeId">
<option value="-1">--请选择--</option>
</select>
</td>
</tr>
<tr>
<td>书籍出版社</td>
<td>
<select id="bookPressId" name="bookPressId">
<option value="-1">--请选择--</option>
</select>
</td>
</tr>
<tr>
<td>文章状态</td>
<td>
<input type="radio" name="bookStatus" value="1" <#if vo.bookStatus == 1>checked</#if>/>上架
<input type="radio" name="bookStatus" value="2" <#if vo.bookStatus == 2>checked</#if>/>下架
</td>
</tr>
<tr>
<td>发布日期</td>
<td>
<input id="edit_book_date" name="bookAddTime" value="${vo.bookAddTime}">
</td>
</tr>
<tr>
<td>文章标签</td>
<td>
<#if vo.bookLabel ??>
<input type="checkbox" name="bookLabel" value="1" <#if vo.bookLabel?contains('1')>checked</#if>/>校园
<input type="checkbox" name="bookLabel" value="2" <#if vo.bookLabel?contains('2')>checked</#if>/>青春
<input type="checkbox" name="bookLabel" value="3" <#if vo.bookLabel?contains('3')>checked</#if>/>政治
<input type="checkbox" name="bookLabel" value="4" <#if vo.bookLabel?contains('4')>checked</#if>/>经济
</#if>
</td>
</tr>
<tr>
<td>书籍描述</td>
<td>
<input name="bookDesc" id="bookDesc" value="${vo.bookDesc}">
</td>
</tr>
<tr>
<td>作者所在省</td>
<td>
<select id="authorProId" name="authorProId">
<option value="-1">--请选择--</option>
</select>
</td>
</tr>
<tr>
<td>作者所在市</td>
<td>
<select id="authorCityId" name="authorCityId">
<option value="-1">--请选择--</option>
</select>
</td>
</tr>
<tr>
<td colspan="2">
<input type="button" value="提交" id="edit_book">
</td>
</tr>
</table>
</form>
<script type="text/javascript" src="${base}/plugins/jquery.min.js"></script>
<script src="${base}/plugins/layui/layui.all.js"></script>
<script>
$(function(){
//类型
$.ajax({
url:"${base}/booktype/listAll",
type:"post",
dataType:"json",
data:"{}",
success:function(data){
for(var x = 0; x < data.length ; x ++){
if(data[x].typeId=="${vo.bookTypeId}"){
add_select_Row("bookTypeId",data[x].typeId,data[x].typeName,"selected");
}else{
add_select_Row("bookTypeId",data[x].typeId,data[x].typeName,"");
}
}
}
});
//出版社
$.ajax({
url:"${base}/bookpress/listAll",
type:"post",
dataType:"json",
data:"{}",
success:function(data){
for(var x = 0; x < data.length ; x ++){
if(data[x].pressId=="${vo.bookPressId}"){
add_select_Row("bookPressId",data[x].pressId,data[x].pressName,"selected");
}else{
add_select_Row("bookPressId",data[x].pressId,data[x].pressName,"");
}
}
}
});
//省
$.ajax({
url:"${base}/location/list",
type:"post",
dataType:"json",
data:"{}",
success:function(data){
for(var x = 0; x < data.length ; x ++){
//console.log(data[x].locationID +","+ data[x].locationName);
if(data[x].locationID=="${vo.authorProId}"){
add_select_Row("authorProId",data[x].locationID,data[x].locationName,"selected");
loadCity(data[x].locationID);
}else{
add_select_Row("authorProId",data[x].locationID,data[x].locationName,"");
}
}
}
});
});
$("#authorProId").on("change",function(){
//市
var parentId = $(this).val();
loadCity(parentId);
});
function loadCity(parentId){
$.ajax({
url:"${base}/location/list",
type:"post",
dataType:"json",
data:{locationID:parentId},
success:function(data){
$("#authorCityId option:gt(0)").remove();
for(var x = 0; x < data.length ; x ++){
//console.log(data[x].locationID +","+ data[x].locationName);
if(data[x].locationID == "${vo.authorCityId}"){
add_select_Row("authorCityId",data[x].locationID,data[x].locationName,"selected");
}else{
add_select_Row("authorCityId",data[x].locationID,data[x].locationName,"");
}
}
}
});
}
function add_select_Row(eleId,contentId,contentTitle,selecval){
$("#"+eleId).append(
"<option "+ selecval +" value='"+ contentId +"'>"+ contentTitle +"</option>"
);
}
//提交表单
$("#edit_book").click(function() {
//进行数据同步
data_sync();
$.ajax({
url:"${base}/book/edit",
data:$("#edit_book_form").serialize(),
type:"post",
dataType:"json",
success:function(data) {
alert("修改成功");
location.href = "${base}/book/list";
}
});
});
//初始化layui相关组件
layui.use(['form', 'upload', 'layedit', 'laydate'], function(){
var form = layui.form;
var upload = layui.upload;
var edit = layui.layedit;
var laydate = layui.laydate;
//初始化编辑器
bookEditor = edit.build("bookDesc");
data_sync = function() {
edit.sync(bookEditor);
}
//初始化日期控件
laydate.render({
elem:"#edit_book_date"
});
var ssdd1;
//普通图片上传--封面
var uploadInst = upload.render({
//绑定上传组件到具体的标签上
elem: '#uploadPic'
//文件上传的后台方法
,url: '${base}/book/uploadBookCover'
//文件上传到后台的对象的属性名,如:此处Book中图片的属性为bPic,控制层接收的参数要与此对应
,field:"bookCover"
//是否开启多文件上传
,multiple:true
//文件上传之前调用,弹出模态窗口
,before: function(obj){
ssdd1 = layer.open({
type: 1
,title: false //不显示标题栏
,closeBtn: false
,shade: 0.4
,moveType: 1 //拖拽模式,0或者1
,content: '<i class="layui-icon layui-anim layui-anim-rotate layui-anim-loop"></i>'
});
//预读本地文件示例,不支持ie8
obj.preview(function(index, file, result){
$('#demo1').html('<img height="80px" src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img">')
});
}
,done: function(data){
//当一次上传结束之后回调函数
$("#edit_book_cover").val(data.filepath);
layer.close(ssdd1);
}
,error: function(){
//演示失败状态,并实现重传
var demoText = $('#demoText');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-mini demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function(){
uploadInst.upload();
});
}
});
});
</script>
</body>
</html>
在回填的过程中需要注意的地方:
①需要使用隐藏域继续传递书籍id,以及书籍地封面,也需要使用隐藏域,在文件上传之后会将图片的名称设置到隐藏域中。
②单选框回填判断“<#if vo.bookStatus == 1>checked</#if>”,多选框的回填判断“<#if vo.bookLabel?contains('1')>checked</#if>”。
③图片的回填需要将img标签放到会预览图片的位置即可“<img height="80px" src="${base}${vo.bookCover!}">”。
④下拉框的回填操作,因为下拉框需要查询数据库,然后在页面加载的时候将查询出来的数据填充到对应的下拉列表中,所以在进行回填并且选中时就需要在添加的时候进行判断,然后为其标签动态的添加“selected”。
⑤在JavaScript中如果需要获取后台传递过来的数据,则需要使用双引号括起来才能取值,否则取不到对应的值,例如:if(data[x].pressId=="${vo.bookPressId}")。
⑥在二级联动回填的时候,与新增的时候还是有区别的,因为需要回填选中对应的option,所以将其封装成为一个函数,以方便省级选中之后调用市级地区的判断。
6、修改listBooks.ftl和showBooks.ftl页面,为其添加修改操作
范例:修改showBooks.ftl文件
<input type="button" value="修改" onclick="editBut(${vo.bookId})">
范例:修改listBooks.ftl文件
function editBut(bookid){
location.href = "${base}/book/editPre?bookId="+bookid;
}
至此,增删改查的操作就都已经完成了。