一、图书列表展示功能
1.1 实现分页功能
提到展示图书列表,就不得不提到分页了
1.1.1 翻页请求对象PageRequest
package com.qiyangyang.springbook.demos.model;
import lombok.Data;
@Data
public class PageRequest {
private Integer currentPage = 1;//当前页
private Integer pageSize = 10;//每页显示个数
private Integer offset;
/**
* 从多少条记录开始查询
* @return
*/
public Integer getOffset() {
return (currentPage-1) * pageSize;
}
}
1.1.2 翻页响应对象
package com.qiyangyang.springbook.demos.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 定义一个泛型类,就是,这个地方不定义具体类型
* 我们在进行对象的生成的时候,它才有具体的类型。
* @param <T>
*/
//上面两个注解用来创建构造方法
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PageResult<T> {
/**
* 返回的结果也是一个泛型
* 不定义具体类型,在对象的创建才会有具体类型
*/
private List<T> records; //当前页数据
private Integer count; //所有记录数
private PageRequest pageRequest; //小驼峰,用来返回给前端当前页数
// 这里将整个对象告诉result。用来给前端获取多少页
}
MySQL语句
1.2使用枚举来处理status/stateCN字段。 (可借阅/不可借阅)
1.3约定前后端交互接口
1.4实现服务器代码
1.4.1控制层:
@RequestMapping("getListByPage")
public PageResult<BookInfo> getListByPage(PageRequest pageRequest){
log.info("查询列表信息,pageRequest:{}",pageRequest);
if(pageRequest.getCurrentPage()< 1){
return null;
}//这里返回null。会导致前端不知道是没有数据为null。还是当前页错误返回null
//先不管,后续改进
/**
* 通过Service来去调用数据库
*/
return bookService.getListByPage(pageRequest);
}
1.4.2 业务层 :
public PageResult<BookInfo> getListByPage(PageRequest pageRequest) {
/**
* 1.查询记录的总数
* 2.查询当前页的数据
*/
Integer count = bookInfoMapper.count();
//bookInfos来接收查询到的数据
List<BookInfo> bookInfos = bookInfoMapper.queryListByPage(pageRequest);
for(BookInfo bookInfo : bookInfos){
/**
* 根据book状态设置描述(stateCN)
*/
bookInfo.setStateCN(BookStatusEnums.getDescByCode(bookInfo.getStatus()).getDesc());
}
return new PageResult<>(bookInfos,count);
}
1.4.3 数据层 :
/**
* 查询总数
* @return
*/
//count(1):返回满足条件的记录数(即行数)。count(1) 和 count(*) 基本等效,都是用于统计记录数。
@Select(("select count(1) from book_info where status <> 0"))
Integer count();
//希望把新添加的图书放到下面,因此order by id desc降序。
@Select("select * from book_info where status <> 0 order by id desc limit #{offset},#{pageSize}")
List<BookInfo> queryListByPage(PageRequest pageRequest);
1.5校验后端
1.6实现前端代码
<tbody>
//这里的内容我们用findHtml变量拼接并传送到这个标签里了
</tbody>
success: function (result) {
var books = result.records;
console.log(books); //如果前端没有报错,那么我们打印日志。观察后端返回结果对不对
var findHtml = ""; //用这个变量来拼接HTML
for (var book of books) {
//拼接html。假如后端返回10个tr那么直接for循环拼接在这里面。findHtml
//我们用单引号拼接,因为里面有双引号
findHtml += '<tr>';
findHtml += '<td><input type="checkbox" name="selectBook" value="' +book.id +'" id="selectBook" class="book-select"></td>';
findHtml += "<td>" + book.id + "</td>";
findHtml += "<td>" + book.bookName + "</td>";
findHtml += "<td>" + book.author + "</td>";
findHtml += "<td>" + book.count + "</td>";
findHtml += "<td>" + book.price + "</td>";
findHtml += "<td>" + book.publish + "</td>";
findHtml += "<td>" + book.stateCN + "</td>";
findHtml += "<td>";
findHtml += '<div class="op">';
findHtml +=
'<a href="book_update.html?bookId=' + book.id + '">修改</a>';
findHtml +=
'<a href="javascript:void(0)" onclick="deleteBook('+book.id +')">删除</a>';
findHtml += "</div>";
findHtml += "</td>";
findHtml += "</tr>";
}
$("tbody").html(findHtml); //塞到tbody这个标签里面
1.7校验前后端
二、修改图书列表功能
2.1约定前后端交互接口
2.2实现服务器端代码
2.2.1控制层:
@RequestMapping("/queryBookById")
public BookInfo queryBookById(Integer bookId){
log.info("查询图书信息,bookId:"+bookId);
if(bookId == null || bookId<=0){
return new BookInfo();
}
return bookService.queryBookById(bookId);
}
@RequestMapping("/updateBook")
//先使用boolean类型返回。后续我们还会再进行完善。
public boolean upDateBook(BookInfo bookInfo){
log.info("修改图书信息, updateBook{}:",bookInfo);
if(!StringUtils.hasLength(bookInfo.getBookName())
|| !StringUtils.hasLength(bookInfo.getAuthor())
|| !StringUtils.hasLength(bookInfo.getPublish())
|| bookInfo.getCount() <=0
|| bookInfo.getPrice()==null){
return false;
}
try {
Integer result = bookService.updateBook(bookInfo);
if(result <= 0){
return false;
}
}catch (Exception e){
log.error("更新图书失败");
return false;
}
return true;
}
2.2.2 业务层 :
public BookInfo queryBookById(Integer bookId) {
return bookInfoMapper.queryBookById(bookId);
}
public Integer updateBook(BookInfo bookInfo) {
return bookInfoMapper.updateBook(bookInfo);
}
2.2.3 数据层 :
/**
* 根据Id查询图书信息
* @param id
* @return
*/
@Select("select * from book_info where status <> 0 and id = #{id}")
BookInfo queryBookById(Integer id);
/**
* 根据Id修改图书信息
*/
Integer updateBook(BookInfo bookInfo);
2.3校验后端
2.3.1校验queryBookById接口
2.3.2校验updateBook接口
2.4实现前端代码
<script type="text/javascript" src="js/jquery.min.js"></script>
<script>
//查询当前ID图书
$.ajax({
type: "get",
url: "book/queryBookById"+location.search,
success:function(book){
if(book!=null){
$("#bookId").val(book.id);
$("#bookName").val(book.bookName);
$("#bookAuthor").val(book.author);
$("#bookStock").val(book.count);
$("#bookPrice").val(book.price);
$("#bookPublisher").val(book.publish);
$("#bookStatus").val(book.status);
}
}
});
//更新当前Id图书
function update() {
$.ajax({
type: "get",
url: "/book/updateBook",
data:$("#updateBook").serialize(),//提交整个表单
success:function(result){
if(result == true){
alert("更新成功");
location.href = "book_list.html"
}else{
alert("更新失败");
}
}
});
}
</script>
2.5整体测试
三、逻辑删除图书
3.1约定前后端交互接口
3.2实现服务器代码
3.2.1控制层:
@RequestMapping("/updateBook")
//先使用boolean类型返回。后续我们还会再进行完善。
public boolean upDateBook(BookInfo bookInfo){
log.info("修改图书信息, updateBook{}:",bookInfo);
if(!StringUtils.hasLength(bookInfo.getBookName())
|| !StringUtils.hasLength(bookInfo.getAuthor())
|| !StringUtils.hasLength(bookInfo.getPublish())
|| bookInfo.getCount() <=0
|| bookInfo.getPrice()==null){
return false;
}
try {
Integer result = bookService.updateBook(bookInfo);
if(result <= 0){
return false;
}
}catch (Exception e){
log.error("更新图书失败");
return false;
}
return true;
}
@RequestMapping("/updateBook")
//先使用boolean类型返回。后续我们还会再进行完善。
public boolean updateBook(BookInfo bookInfo){
log.info("修改图书信息, updateBook{}:",bookInfo);
if(bookInfo.getId()<0){
return false;
}
try {
Integer result = bookService.updateBook(bookInfo);
if(result <= 0){
return false;
}
}catch (Exception e){
log.error("更新图书失败");
return false;
}
return true;
}
3.2.2 业务层 :
public Integer updateBook(BookInfo bookInfo) {
return bookInfoMapper.updateBook(bookInfo);
}
3.2.3 数据层 :
同之前的update一样
/**
* 根据Id修改图书信息
*/
Integer updateBook(BookInfo bookInfo);
<update id="updateBook">
update book_info
<set>
<if test="bookName != null">
book_name = #{bookName},
</if>
<if test="author != null">
author = #{author},
</if>
<if test="count != null">
count = #{count},
</if>
<if test="price != null">
price = #{price},
</if>
<if test="publish != null">
publish = #{publish},
</if>
<if test="status != null">
status = #{status},
</if>
</set>
where id = #{id}
</update>
校验后端接口
3.3实现前端代码
function deleteBook(id) {
//删除图书
var isDelete = confirm("确认删除?");
if (isDelete) {
$.ajax({
type: "post",
url: "/book/updateBook",
data:{
id: id,
status: 0
},
success:function(result){
if(result == true){
alert("删除成功");
location.href = "book_list.html";
}
}
});
}
}
3.4整体校验
四、批量逻辑删除
4.1定义前后端交互接口
4.2实现服务器端代码
4.2.1控制层:
@RequestMapping("/batchDelete")
public boolean batchDelete(@RequestParam List<Integer> ids){
log.info("批量删除数据,ids:{}",ids);
try {
Integer result = bookService.batchDelete(ids);
if(result <= 0){
return false;
}
}catch (Exception e){
log.info("批量删除失败,id:{},e:{}", ids, e);
return false;
}
return true;
}
4.2.2 业务层 :
public Integer batchDelete(List<Integer> ids) {
return bookInfoMapper.batchDelete(ids);
}
4.2.3 数据层 :
Integer batchDelete(@Param("ids") List<Integer> ids);
<update id="batchDelete">
update book_info
set status = 0
where id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</update>
4.3后端校验
4.4实现前端代码
function batchDelete() {
var isDelete = confirm("确认批量删除?");
if (isDelete) {
//获取复选框的id
var ids = [];
$("input:checkbox[name='selectBook']:checked").each(function () {
ids.push($(this).val());
});
console.log(ids);
$.ajax({
type: "post",
url: "/book/batchDelete?ids="+ids,
success:function(result){
if(result == true){
alert("批量删除成功");
location.href = "book_list.html";
}else{
alert("删除失败,请联系管理员!");
}
}
});
}
}