springboot+mybatis实现数据分页(三种方式)

项目准备

1.创建用户表
在这里插入图片描述
2.使用spring初始化向导快速创建项目,勾选mybatis,web,jdbc,driver
添加lombok插件


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.hao</groupId>
    <artifactId>spring-boot-crud-end</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-crud-end</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

一、使用原生Java实现分页

1.UserMapper接口

@Mapper
@Repository
public interface UserMapper {

    int selectCount();
    List<User> selectUserFindAll();
}

2.整合mybatis(application.yaml)

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/crud?serverTimezone=UTC
    username: root
    password: hao20001010

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.hao.springboot.entity

3.测试dao层(成功

@SpringBootTest
class SpringBootCrudEndApplicationTests {

    @Autowired
    UserMapper userMapper;

    @Test
    void contextLoads() {
        List<User> users = userMapper.selectUserFindAll();
        for(User user:users){
            System.out.println(user);
        }
    }

    @Test
    void contextLoads2(){

    }
}

4.编写service层

public interface UserService {

    int selectCount();

    List<User> selectUserByArray(int currentPage,int pageSize);
}
/**
 * @author:抱着鱼睡觉的喵喵
 * @date:2020/12/26
 * @description:
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    @Override
    public int selectCount() {
        int count = userMapper.selectCount();
        return count;
    }

    /**
     * 原始分页逻辑实现
     * @param currentPage	当前页
     * @param pageSize		每页的数量
     * @return
     */
    @Override
    public List<User> selectUserByArray(int currentPage, int pageSize) {
        List<User> users = userMapper.selectUserFindAll();
        int count=selectCount();
        int startCurrentPage=(currentPage-1)*pageSize;        //开启的数据
        int endCurrentPage=currentPage*pageSize;        //结束的数据
        int totalPage=count/pageSize;                   //总页数
        if (currentPage>totalPage || currentPage<=0){
            return null;
        }else{
            return users.subList(startCurrentPage,endCurrentPage);
        }
    }
}

5.controller层

@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping("/user/{currentPage}/{pageSize}")
    public List<User> selectFindPart(@PathVariable("currentPage") int currentPage, @PathVariable("pageSize") int pageSize){


        List<User> list = userService.selectUserByArray(currentPage, pageSize);
        if (list==null){
            throw new UserNotExistException("访问出错!QWQ");
        }else{
            return list;
        }
    }
}

6.异常处理

public class UserNotExistException extends RuntimeException{

    private static final long serialVersionUID = 1L;
    private String msg;
    public UserNotExistException(String msg) {
        super("user not exist");
        this.msg=msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

7.controller异常处理类

/**
 * @author:抱着鱼睡觉的喵喵
 * @date:2020/12/26
 * @description:
 */
@ControllerAdvice			//处理controller层出现的异常
public class ControllerExceptionHandler {


    @ExceptionHandler(UserNotExistException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) //状态码
    public Map<String,Object> handlerUserNotExistException(UserNotExistException ex){
        Map<String,Object> result=new HashMap<>();
        result.put("msg", ex.getMsg());
        result.put("message", ex.getMessage());
        return result;
    }
}

8.访问http://localhost:8080/user/5/10出现如下

{“msg”:“访问出错!QWQ”,“message”:“user not exist”}

9.访问http://localhost:8080/user/2/3 出现如下

[{“id”:4,“userName”:“sky”,“password”:“789”},{“id”:5,“userName”:“nulls”,“password”:“tom”},{“id”:6,“userName”:“zsh”,“password”:“zsh”}]

总结:
缺点:数据库查询并返回所有的数据,而我们需要的只是极少数符合要求的数据。当数据量少时,还可以接受。当数据库数据量过大时,每次查询对数据库和程序的性能都会产生极大的影响。


二、通过sql语句进行分页操作

1.在UserMapper接口中新增一个方法

@Mapper
@Repository
public interface UserMapper {

//原生分页
    int selectCount();
    List<User> selectUserFindAll();
//通过sql语句进行分页
    List<User> selectBySql(Map<String,Object> map);
}

2.UserService接口中新增方法,以及UserServiceImpl类中进行重写

public interface UserService {

    int selectCount();

    /**
     * 原生分页
     * @param currentPage
     * @param pageSize
     * @return
     */
    List<User> selectUserByArray(int currentPage,int pageSize);

    /**
     * 通过sql分页
     * @param currentPage
     * @param pageSize
     * @return
     */
    List<User> selectUserBySql(int currentPage,int pageSize);
}
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    @Override
    public int selectCount() {
        int count = userMapper.selectCount();
        return count;
    }

    /**
     * 原始分页逻辑实现
     * @param currentPage
     * @param pageSize
     * @return
     */
    @Override
    public List<User> selectUserByArray(int currentPage, int pageSize) {
        List<User> users = userMapper.selectUserFindAll();
        int count=selectCount();
        int startCurrentPage=(currentPage-1)*pageSize;        //从第几个数据开始
        int endCurrentPage=currentPage*pageSize;        //结束的数据
        int totalPage=count/pageSize;                   //总页数
        if (currentPage>totalPage || currentPage<=0){
            return null;
        }else{
            return users.subList(startCurrentPage,endCurrentPage);
        }
    }
/**
*通过sql语句进行分页
*/
    @Override
    public List<User> selectUserBySql(int currentPage, int pageSize) {
        Map<String,Object> map=new HashMap<>();
        int startCurrentPage=(currentPage-1)*pageSize;        //从第几个数据开始
        int count=selectCount();
        int totalPage=count/pageSize;                   //总页数
        if (currentPage>totalPage || currentPage<=0){
            return null;
        }else{
            map.put("currentPage",startCurrentPage);
            map.put("pageSize",pageSize);
            List<User> list = userMapper.selectBySql(map);
            return list;
        }

    }
}

3.controller层编写

@RestController
public class UserController {

    @Autowired
    UserService userService;
//Java原生实现分页模块
    @GetMapping("/user/{currentPage}/{pageSize}")
    public List<User> selectFindByJava(@PathVariable("currentPage") int currentPage, @PathVariable("pageSize") int pageSize){


        List<User> list = userService.selectUserByArray(currentPage, pageSize);
        if (list==null){
            throw new UserNotExistException("访问出错!QWQ");
        }else{
            return list;
        }
    }
//sql分页方法模块
    @GetMapping("/user2/{currentPage}/{pageSize}")
    public List<User> selectFindBySql(@PathVariable("currentPage") int currentPage, @PathVariable("pageSize") int pageSize){


        List<User> list = userService.selectUserBySql(currentPage,pageSize);
        if (list==null){
            throw new UserNotExistException("访问出错!QWQ");
        }else{
            return list;
        }
    }
}

4.UserMapper.xml添加查询条件,使用limit进行分页

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.hao.springboot.mapper.UserMapper">

    <resultMap id="user" type="com.hao.springboot.entity.User">
        <result column="user_name" property="userName"/>
        <result column="password" property="password"/>
    </resultMap>
    <select id="selectUserFindAll" resultMap="user">
        select * from user
    </select>

    <select id="selectCount" resultType="integer">
        select count(*) from user
    </select>

    <select id="selectBySql" parameterType="map" resultType="com.hao.springboot.entity.User">
        select * from user limit #{currentPage} , #{pageSize}
    </select>
</mapper>

5.启动访问http://localhost:8080/user2/5/10 出现如下

{“msg”:“访问出错!QWQ”,“message”:“user not exist”}

接着正确访问http://localhost:8080/user2/2/2

[{“id”:3,“userName”:“tom”,“password”:“456”},{“id”:4,“userName”:“sky”,“password”:“789”}]

总结:
缺点:虽然这里实现了按需查找,每次检索得到的是指定的数据。但是每次在分页的时候都需要去编写limit语句,很冗余。而且不方便统一管理,维护性较差。所以我们希望能够有一种更方便的分页实现。


三、拦截器实现分页

  • 10
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
# Spring Boot 集成 MyBatis, 分页插件 PageHelper, 通用 Mapper ## 项目依赖 ```xml <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!--mapper--> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!--pagehelper--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> ``` ## Spring DevTools 配置 在使用 DevTools 时,通用Mapper经常会出现 class x.x.A cannot be cast to x.x.A。 同一个类如果使用了不同的类加载器,就会产生这样的错误,所以解决方案就是让通用Mapper和实体类使用相同的类加载器即可。 DevTools 默认会对 IDE 中引入的所有项目使用 restart 类加载器,对于引入的 jar 包使用 base 类加载器,因此只要保证通用Mapper的jar包使用 restart 类加载器即可。 在 `src/main/resources` 中创建 META-INF 目录,在此目录下添加 spring-devtools.properties 配置,内容如下: ```properties restart.include.mapper=/mapper-[\\w-\\.]+jar restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar ``` 使用这个配置后,就会使用 restart 类加载加载 include 进去的 jar 包。 ## 集成 MyBatis Generator 通过 Maven 插件集成的,所以运行插件使用下面的命令: >mvn mybatis-generator:generate Mybatis Geneator 详解: >http://blog.csdn.net/isea533/article/details/42102297 ## application.properties 配置 ```properties #mybatis mybatis.type-aliases-package=tk.mybatis.springboot.model mybatis.mapper-locations=classpath:mapper/*.xml #mapper #mappers 多个接口时逗号隔开 mapper.mappers=tk.mybatis.springboot.util.MyMapper mapper.not-empty=false mapper.identity=MYSQL #pagehelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql ``` ## application.yml 配置 完整配置可以参考 [src/main/resources/application-old.yml](https://github.com/abel533/MyBatis-Spring-Boot/blob/master/src/main/resources/application-old.yml) ,和 MyBatis 相关的部分配置如下: ```yaml mybatis: type-aliases-package: tk.mybatis.springboot.model mapper-locations: classpath:mapper/*.xml mapper: mappers: - tk.mybatis.springboot.util.MyMapper not-empty: false identity: MYSQL pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql ``` 注意 mapper 配置,因为参数名固定,所以接收参数使用的对象,按照 Spring Boot 配置规则,大写字母都变了带横线的小写字母。针对如 IDENTITY(对应i-d-e-n-t-i-t-y)提供了全小写的 identity 配置,如果 IDE 能自动提示,看自动提示即可。 ## SSM集成的基础项目 >https://github.com/abel533/Mybatis-Spring ## MyBatis工具 http://www.mybatis.tk - 推荐使用 Mybatis 通用 Mapper3 https://github.com/abel533/Mapper - 推荐使用 Mybatis 分页插件 PageHelper https://github.com/pagehelper/Mybatis-PageHelper ## 作者信息 - 作者博客:http://blog.csdn.net/isea533 - 作者邮箱:abel533@gmail.com
首先,需要在pom.xml中引入相应的依赖,这里以MySQL数据库为例: ```xml <!-- SpringBoot Web模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- SpringBoot Mybatis模块 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> ``` 其次,需要配置Mybatis数据库连接,可以在application.yml中配置: ```yml spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC&useSSL=false&characterEncoding=utf8 username: root password: root mybatis: config-location: classpath:mybatis-config.xml mapper-locations: classpath:mapper/*.xml ``` 其中,`datasource`为数据源的基本信息,`mybatis`则是Mybatis的配置信息,包括配置文件的位置和Mapper文件的位置。 接下来,需要编写Mapper接口和对应的Mapper XML文件。以User表为例: ```java public interface UserMapper { List<User> findUserByPage(@Param("start") Integer start, @Param("pageSize") Integer pageSize); } ``` ```xml <mapper namespace="com.example.demo.mapper.UserMapper"> <select id="findUserByPage" resultType="com.example.demo.entity.User"> select * from user limit #{start},#{pageSize} </select> </mapper> ``` 其中,`findUserByPage`方法为分页查询方法,`start`为起始位置,`pageSize`为每页数量。 最后,编写Controller层和前端页面。以UserController为例: ```java @Controller public class UserController { @Autowired private UserMapper userMapper; @GetMapping("/user") public String findUserByPage(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, Model model) { Integer start = (pageNum - 1) * pageSize; List<User> userList = userMapper.findUserByPage(start, pageSize); PageInfo pageInfo = new PageInfo(userList); model.addAttribute("pageInfo", pageInfo); return "user"; } } ``` 其中,`findUserByPage`方法接收两个参数:`pageNum`和`pageSize`,表示当前页和每页数量。通过计算获得起始位置,调用Mapper接口进行分页查询,并通过`PageInfo`类将查询结果传递给前端页面。 在前端页面中通过`th:each`循环遍历查询结果,并通过`th:href`生成分页链接。以user.html为例: ```html <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>User List</title> </head> <body> <table border="1"> <thead> <tr> <th>ID</th> <th>Name</th> <th>Age</th> <th>Gender</th> </tr> </thead> <tbody> <tr th:each="user : ${pageInfo.list}"> <td th:text="${user.id}"></td> <td th:text="${user.name}"></td> <td th:text="${user.age}"></td> <td th:text="${user.gender}"></td> </tr> </tbody> </table> <div> <a th:href="@{/user?pageNum=1}">首页</a> <a th:href="@{/user?pageNum=${pageInfo.prePage}}">上一页</a> <a th:href="@{/user?pageNum=${pageInfo.nextPage}}">下一页</a> <a th:href="@{/user?pageNum=${pageInfo.pages}}">尾页</a> </div> </body> </html> ``` 其中,`pageInfo.list`为查询结果列表,通过`th:each`循环遍历生成表格数据。底部的分页链接则通过`th:href`生成相应的链接。 到这里,一个简单的分页查询就完成了。需要注意的是,以上代码仅为示例,具体实现方式可能会有所不同,需要按照实际需求进行调整。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thecoastlines

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值