分页是一种在处理大量数据时非常重要的技术手段之一,当数据量很大的时候,如果一次性加载所有数据,会消耗大量的内存和计算资源。但是如果只取部分需要的数据,可以减少数据的加载量,这样的话由于数据量少了,所以加载数据的速度也就有所提升了。
并且前端展示大量数据可能会导致浏览器卡顿或者渲染时间过长,而通过分页技术分批次加载数据,改善前端显示效果和用户交互体验。
从数据库底层查询角度来讲,分页查询可以避免全表扫描提升查询效率。
下面我们就来详细介绍几种在SpringBoot项目中实现分页查询的方法。
Spring Data JPA 中的 Pageable
在Spring Data JPA 中,我们可以通过Pageable接口来实现分页查询的效果,如下所示。
第一步、需要引入JPA的依赖包以及数据库依赖,如下所示。
<dependencies>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 数据库驱动,例如 H2 数据库 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
第二步、假设存在一个用户实体类对象,可以通过JpaRepository接口来实现数据DTO查询访问。如下所示。
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// Getters and Setters
}
//UserRepository 接口对象
public interface UserRepository extends JpaRepository<User, Long> {
}
第三步、在业务服务层对象中实现分页查询逻辑,如下所示。
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public Page<User> findPaginated(int page, int size) {
Pageable pageable = PageRequest.of(page, size);
return userRepository.findAll(pageable);
}
}
通过Pageable来拦截分页请求,实现分页查询操作。接下来的就可以在Controller中使用Service层的分页查询功能来实现分页查询接口,如下所示。
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return userService.findPaginated(page, size);
}
}
这样我们就可以实现分页查询接口了。上面我们展示了如何使用了JPA中的Pageable接口来实现分页查询操作。那么还有没有其他的方式来实现分页查询操作呢,下面我们来介绍一下通过MyBatis插件PageHelper来实现查询分页操作。
MyBatis PageHelper插件
第一步、需要在SpringBoot项目中引入PageHelper和MyBatis依赖插件,如下所示。
<dependencies>
<!-- PageHelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
<!-- MyBatis Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- 数据库驱动,例如 H2 数据库 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
第二步和第三步的操作与上面的操作是类似的,需要创建一个实体类对象,但是由于我们引入的实MyBatis的依赖配置实现,所以需要创建一个MyBatis的Mapper接口用来进行数据查询操作,如下所示。
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user")
List<User> findAll();
}
配置Mapper的UserMapper映射文件,如下所示。
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.UserMapper">
<select id="findAll" resultType="com.example.demo.User">
SELECT * FROM user
</select>
</mapper>
第四步、创建Service层的对象用来实现分页查询逻辑,如下所示。
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public PageInfo<User> findPaginated(int page, int size) {
PageHelper.startPage(page, size);
List<User> users = userMapper.findAll();
return new PageInfo<>(users);
}
}
接下来就是在Controller层对象中调用Service层的分页方法来实现分页查询功能。如下所示。
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
public PageInfo<User> getUsers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
return userService.findPaginated(page, size);
}
}
总结
在上面的操作中,我们分别演示了通过JPA和MyBatis技术来实现SpringBoot应用分页,分页操作是处理大批量数据查询的有效手段之一、通过分页技术可以提升系统的查询性能,减少系统操作延迟,并且改善了用户的查询体验。在实际开发工作中分页查询操作几乎是一个必须的功能,例如在管理系统的中的分页查询、在一些移动端的上拉加载操作都是通过分页技术来提升应用的用户体验。