博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springboot+mybatis实现分页
阅读量:3891 次
发布时间:2019-05-23

本文共 11777 字,大约阅读时间需要 39 分钟。

分页成果展示:

1.整合mybatis框架

1.数据库准备好数据:我网站中的数据时通过python爬虫,直接保存到数据库中的。图片直接保存的豆瓣的url。

2.整合mybatis依赖和mybatis分页插件:

根据此教程完成初步操作:(不要选择kotlin即可)

然后添加分页插件依赖:官网

//mybatis分页插件

compile group: 'com.github.pagehelper', name:'pagehelper-spring-boot-starter',version: '1.2.10'
推荐阅读:(读不读都行)
2.
3.
 

2.结合mybatis分页插件编写动态sql实现分页功能。

有三种分页方式:。我选择的是后台分页。

1.约定好url接口(REST风格)

  因为使用mybatis分页插件直接得到的是json数据,所以我直接使用接口来访问和传递数据。如果不想用接口的话,也可以使用模版等方式,不过我就不说了。

  使用接口后,前端可以直接通过ajax来通过rest风格接口获取数据。

示例:

  1. 如果什么都不选择:
  2. {"total":4867,"list":[{"id":1292052,"name":"肖申克的救赎","score":9.6,"url":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg"}],"pageNum":0,"pageSize":1,"size":1,"startRow":1,"endRow":1,"pages":4867,"prePage":0,"nextPage":1,"isFirstPage":false,"isLastPage":false,"hasPreviousPage":false,"hasNextPage":true,"navigatePages":8,"navigatepageNums":[1,2,3,4,5,6,7,8],"navigateFirstPage":1,"navigateLastPage":8}
  3. 比如选择:剧情分类(genres=11),地区为中国(place=中国),年代为2018(beginyear和endyear都为2018),排序为最热电影(sort=0),第一页(start=1),每页最多条目(size=10)来发送url请求。
  4. {"total":6,"list":[{"id":26752088,"name":"我不是药神","score":9.0,"url":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2519070834.jpg"},{"id":26425063,"name":"无双","score":8.2,"url":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2535096871.jpg"},{"id":26647117,"name":"暴裂无声","score":8.2,"url":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2517333671.jpg"},{"id":27110296,"name":"无名之辈","score":8.3,"url":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2539661066.jpg"},{"id":25716096,"name":"狗十三","score":8.5,"url":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2540474819.jpg"},{"id":30206517,"name":"切尔诺贝利之春","score":8.0,"url":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2520682504.jpg"}],"pageNum":1,"pageSize":10,"size":6,"startRow":1,"endRow":6,"pages":1,"prePage":0,"nextPage":0,"isFirstPage":true,"isLastPage":true,"hasPreviousPage":false,"hasNextPage":false,"navigatePages":8,"navigatepageNums":[1],"navigateFirstPage":1,"navigateLastPage":1}

2.使用mybatis pagehelper分页插件。

我直接给出我的流程:

1.编写controller层(根据之前设计好的接口来)

@RestControllerpublic class CategoryController {    @Autowired    private CategoryService categoryService;    @GetMapping("/page")    public PageInfo
page(@RequestParam(value = "start",defaultValue = "1") String start, @RequestParam(value = "size",defaultValue = "6") String size, @RequestParam(value = "genres",required=false) String genres , @RequestParam(value = "sort",defaultValue = "0") String sort, @RequestParam(value = "beginyear",required=false) String beginyear, @RequestParam(value = "endyear",required=false) String endyear, @RequestParam(value = "place",required=false) String place ){ Map
myMap= new HashMap<>(7); myMap.put("start",start); myMap.put("size",size); myMap.put("genres",genres); myMap.put("sort",sort); myMap.put("beginyear",beginyear); myMap.put("endyear",endyear); myMap.put("place",place); return categoryService.homePage(myMap); }}

2.编写service层:

 在执行sql前添加插件,完成分页功能:参考

我们知道,在中,分页的sql是使用limit来做,如果我们自己写sql,那分页肯定是没有任何问题的。但是一旦model多了起来,复杂了起来,我们很自然的想到使用mybatis的逆向工程来生成相应的po和mapper,但是同时也会带来弊端,比如这里的分页问题就不好解决了。 所以还是选择使用分页插件。

查询的sql语句执行之前,添加一行代码PageHelper.startPage(x,y);第一个参数表示第几页,第二个参数表示每页显示的记录数。这样在执行sql后就会将记录按照语句中设置的那样进行分页。如果需要获取总记录数的话,需要PageInfo类的对象,这个对象可以获取总记录数,下面看下测试的代码。

public interface CategoryService {    PageInfo homePage(Map
map);}@Servicepublic class CategoryServiceImpl implements CategoryService { @Resource private MovieShowBeanMapper movieShowBeanMapper; @Resource private CategoryMapper categoryMapper; @Override public PageInfo homePage(Map
myMap) { //设置分页参数 PageHelper.startPage(Integer.valueOf(myMap.get("start")),Integer.valueOf(myMap.get("size"))); List
list=movieShowBeanMapper.findShowMovie(myMap.get("genres"), myMap.get("sort"), myMap.get("beginyear"), myMap.get("endyear"), myMap.get("place")); //使用对象包装返回结果 return new PageInfo(list); }}

3.编写dao层(或者说是mapper)

因为需要根据选择来判断是否添加限定条件,所以必须是动态sql。

因为注解方式很简单,所以我直接使用注解的方式完成操作。

参考阅读:

@SelectProvider(type = MovieShowSqlProvider.class, method = "selectShow"):使用MovieShowSqlProvider.class这个类中的方法selectShow返回的sql字符串  作为查询的语句。

@Results注解:结果映射的列表, 包含了一个特别结果列如何被映射到属性或字段的详情。属性:value, id。value 属性是 Result 注解的数组。这个id的属性是结果映射的名称可以省略。

@Result注解:column为数据库字段名,porperty为实体类属性名,jdbcType为数据库字段数据类型,id为是否为主键。

public interface MovieShowBeanMapper {    @SelectProvider(type = MovieShowSqlProvider.class, method = "selectShow")    @Results(value = {            @Result( id=true, property = "id",column = "id"),            @Result(property = "name",column = "name"),            @Result(property = "score",column = "score")    })    List
findShowMovie( @Param("genres") String genres , @Param("sort") String sort, @Param("beginyear") String beginyear, @Param("endyear") String endyear, @Param("place") String place );}

4.编写mapper中用到的动态sql:MovieShowSqlProvider类

参考:

然后在这个类中进行sql语句的拼接

 tempSql=new SQL().SELECT("movie_id").FROM("class_contact");
因为是分页查询,使用的是子查询的方式

public class MovieShowSqlProvider {   /*完整的sql语句    SELECT m.id,m.name,m.time from movie m WHERE id in (        SELECT movie_id from place WHERE name ="中国大陆"         and movie_id in         (SELECT movie_id from class_contact WHERE class_id=11)        ) and YEAR(m.time)>1995 and  YEAR(m.time)<=2018         ORDER BY(YEAR(m.time)) desc*/    public String selectShow(Map
map){ SQL tempSql=null; String order="order by m.comment_num"; //1.是否有分类 if(map.get("genres") != null){ tempSql=new SQL().SELECT("movie_id").FROM("class_contact"); if(map.get("place") != null){ SQL tempSql2=new SQL().SELECT("movie_id").FROM("place") .WHERE("name=#{place}"); tempSql.WHERE("movie_id in("+tempSql2+")") .WHERE("class_id=#{genres}"); } else{ tempSql.WHERE("class_id=#{genres}"); } } else{ if(map.get("place") != null){ tempSql=new SQL().SELECT("movie_id").FROM("place") .WHERE("name=#{place}"); } } //判断排序方式 SQL finalTempSql = tempSql; return new SQL(){ { SELECT("m.id,m.name,m.score,m.url"); FROM("movie m"); if(finalTempSql !=null) WHERE("m.id in("+finalTempSql+")"); if(map.get("beginyear") != null) WHERE("YEAR(m.time)>=#{beginyear}"); if(map.get("endyear") != null) WHERE("YEAR(m.time)<=#{endyear}"); //排序 if(map.get("sort").equals("1")){ ORDER_BY("m.time desc"); } else if(map.get("sort").equals("2")){ ORDER_BY("m.score desc"); } else{ ORDER_BY("m.comment_num desc"); } } }.toString(); }}

好啦,单元测试自己写喽。还有注意写异常处理。(我暂时还不会写)

相关阅读:

1.

2.

3.

4.

5.

逆向工程可用可不用,对我工程来说是没必要的。

3.前端发送请求来获取数据。

直接通过点按钮击触发参数,通过参数发送get请求,参数放在里面。

不过因为不太清楚get请求,我直接使用的拼接url来发送get请求。

然后前端通过js进行数据处理,我听说前端也有数据处理插件,不过没有查询资料。感兴趣的可以查一查。

//请求jsonfunction sendurl() {    //先构造基础部分    baseUrl="/page?size="+size+"&start="+start+"&sort="+sort;    if(genres!=""){        baseUrl+="&genres="+genres;    }    if(place!=""){        baseUrl+="&place="+place;    }    if(beginyear!=""){        baseUrl+="&beginyear="+beginyear;    }    if(endyear!=""){        baseUrl+="&endyear="+endyear;    }    $.ajax({        //访问地址        url: baseUrl,        //访问方式,一般有GET或POST两种        type: 'GET',        //返回的数据格式,这个是可选参数,jquery回默认判断返回参数的类型        dataType: 'json'        /*//发送的数据        data: {            param1: 'value1',            param2: 'value2'        },*/    })    //成功后的处理函数,res为服务器返回的数据        .done(function(data) {            //删除当前页面显示:            $(".want_remove").remove();            toastr.success('获取数据成功:ヾ(o◕∀◕)ノヾ');            //因为设置了type,返回的就是json对象            //构造电影模块            //背景变量            var myback=["bg-danger","bg-primary","bg-success","bg-info","bg-secondary"]            var lineNum=size/2;            $.each(data.list,function(idx,item) {                myscore=Math.round(item.score/2);                var myn=idx%5;                var star="";                for(i=0;i
\n" + "
\n" + "
\"Card\n" + "
\n" + "

"+item.name+"

\n" + "

"+star+item.score+"

\n" + "
\n" + "
\n" + " " ); } else{ $("#second_row").append( "
\n" + "
\n" + "
\"Card\n" + "
\n" + "

"+item.name+"

\n" + "

"+star+item.score+"

\n" + "
\n" + "
\n" + "
" ); } }) // $(".want_remove").fadeIn("slow"); //构造分页栏 //显示基本信息 $("#myresult").text("共"+data.total+"部;"+data.pages+"页"); //删除之前的标签 $(".can_remove").remove(); //设置标签页 /*for(i=0;i
" + item + "" ); } else{ $("#list_next").before( "
  • " + item+ "
  • " ); } }) //如果前一页不存在 if(!data.hasPreviousPage) $("#list_pre").addClass("disabled"); else{ $("#list_pre").removeClass("disabled"); } //如果后一页不存在 if(!data.hasNextPage) $("#list_next").addClass("disabled"); else{ $("#list_next").removeClass("disabled"); } //分别是数组 console.log("success"); }) //失败后的处理函数 .fail(function() { toastr.error('Error:肯定不是服务器炸了ヾノ≧∀≦)o死开!'); console.log("error"); }) //结束后的处理函数,不管成功失败都执行 /*.always(function(res) { console.log("complete"); });*/ //get不能判断是否失败 /*$.get(baseUrl,function(result){ alert(result); });*/}

    最终完成喽。

    转载地址:http://nfihn.baihongyu.com/

    你可能感兴趣的文章
    新开发的体重管理项目----用纯php模仿yii2框架建立的
    查看>>
    JavaScript面向对象编程指南 的笔记
    查看>>
    在 2016 年做 PHP 开发是一种什么样的体验?(一)
    查看>>
    PHP获取客户端的IP
    查看>>
    从头开始学习yii2---1.搭建yii2开发环境
    查看>>
    从头开始学习yii2---3.语言包的配置
    查看>>
    yii2-表单验证的一些规则
    查看>>
    索引相关问题
    查看>>
    php面试可能会被问道的技术题汇总
    查看>>
    php面试题1-线程和进程的区别(顺带提下协程)
    查看>>
    php面试题2-用到过的传输协议
    查看>>
    php面试题3-yii2和yii的不一样的地方
    查看>>
    IOS 一些好的框架和 技术大牛的博客
    查看>>
    Java 和 Object-c的区别
    查看>>
    Windows环境下Android NDK环境搭建
    查看>>
    NDK Build 用法(NDK Build)
    查看>>
    Android NDK开发起步Hello Jni
    查看>>
    [已解决]AutoCompleteTextView 不显示匹配的内容,因为将空的内容添加进去了
    查看>>
    object c 归档和解档,其实就是java中的序列化和反序列化
    查看>>
    object c的浅拷贝(地址拷贝)和深拷贝(对象拷贝)
    查看>>