本文目录导读:

我来为您详细介绍Java实现数据分页查询的几种常见方法。
基础分页实现(手动计算)
分页参数类
public class PageRequest {
private int page; // 当前页码
private int size; // 每页记录数
public PageRequest(int page, int size) {
this.page = page;
this.size = size;
}
// 计算偏移量
public int getOffset() {
return (page - 1) * size;
}
// getter/setter
public int getPage() { return page; }
public void setPage(int page) { this.page = page; }
public int getSize() { return size; }
public void setSize(int size) { this.size = size; }
}
分页结果类
public class PageResult<T> {
private List<T> content; // 当前页数据
private int page; // 当前页码
private int size; // 每页记录数
private long totalElements; // 总记录数
private int totalPages; // 总页数
private boolean first; // 是否是第一页
private boolean last; // 是否是最后一页
public PageResult(List<T> content, PageRequest pageRequest, long totalElements) {
this.content = content;
this.page = pageRequest.getPage();
this.size = pageRequest.getSize();
this.totalElements = totalElements;
this.totalPages = (int) Math.ceil((double) totalElements / size);
this.first = page == 1;
this.last = page >= totalPages;
}
// getter/setter
// ...
}
手动分页实现
public class ManualPaginationService {
// 模拟数据源
private List<String> mockData = new ArrayList<>();
{
// 初始化100条测试数据
for (int i = 1; i <= 100; i++) {
mockData.add("数据-第" + i + "条");
}
}
// 手动分页查询
public PageResult<String> paginate(PageRequest pageRequest) {
// 1. 获取总记录数
long total = mockData.size();
// 2. 计算偏移量和结束位置
int fromIndex = pageRequest.getOffset();
int toIndex = Math.min(fromIndex + pageRequest.getSize(), mockData.size());
// 3. 检查参数合法性
if (fromIndex >= mockData.size()) {
return new PageResult<>(new ArrayList<>(), pageRequest, total);
}
// 4. 截取子列表
List<String> pageData = mockData.subList(fromIndex, toIndex);
// 5. 返回分页结果
return new PageResult<>(pageData, pageRequest, total);
}
}
JDBC实现分页
public class JdbcPaginationService {
private DataSource dataSource;
public JdbcPaginationService(DataSource dataSource) {
this.dataSource = dataSource;
}
// 分页查询方法
public PageResult<User> findUsersByPage(PageRequest pageRequest) {
String countSql = "SELECT COUNT(*) FROM users";
String querySql = "SELECT * FROM users LIMIT ? OFFSET ?";
List<User> users = new ArrayList<>();
long total = 0;
try (Connection conn = dataSource.getConnection()) {
// 1. 查询总记录数
try (PreparedStatement countStmt = conn.prepareStatement(countSql);
ResultSet countRs = countStmt.executeQuery()) {
if (countRs.next()) {
total = countRs.getLong(1);
}
}
// 2. 查询当前页数据
try (PreparedStatement queryStmt = conn.prepareStatement(querySql)) {
queryStmt.setInt(1, pageRequest.getSize());
queryStmt.setInt(2, pageRequest.getOffset());
try (ResultSet rs = queryStmt.executeQuery()) {
while (rs.next()) {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
users.add(user);
}
}
}
} catch (SQLException e) {
throw new RuntimeException("数据库查询失败", e);
}
return new PageResult<>(users, pageRequest, total);
}
}
MyBatis Plus分页
配置分页插件
@Configuration
@MapperScan("com.example.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
Mapper接口
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 分页查询
IPage<User> selectUserPage(IPage<User> page, @Param("name") String name);
}
Mapper XML
<select id="selectUserPage" resultType="User">
SELECT * FROM users
<where>
<if test="name != null and name != ''">
name LIKE CONCAT('%', #{name}, '%')
</if>
</where>
</select>
服务层调用
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public PageResult<User> getUsersByPage(int page, int size, String name) {
// 创建分页对象
Page<User> pageParam = new Page<>(page, size);
// 执行分页查询
IPage<User> pageResult = userMapper.selectUserPage(pageParam, name);
// 转换结果
PageResult<User> result = new PageResult<>();
result.setContent(pageResult.getRecords());
result.setPage((int) pageResult.getCurrent());
result.setSize((int) pageResult.getSize());
result.setTotalElements(pageResult.getTotal());
result.setTotalPages((int) pageResult.getPages());
result.setFirst(pageResult.isFirst());
result.setLast(pageResult.isLast());
return result;
}
}
Spring Data JPA分页
@Service
public class UserJpaService {
@Autowired
private UserRepository userRepository;
public Page<User> getUsersByPage(int page, int size) {
// 创建Pageable对象
Pageable pageable = PageRequest.of(page - 1, size, Sort.by("id").descending());
// 执行分页查询
return userRepository.findAll(pageable);
}
// 带条件的分页查询
public Page<User> searchUsers(String name, int page, int size) {
Pageable pageable = PageRequest.of(page - 1, size);
// 使用Specification进行条件查询
Specification<User> spec = (root, query, cb) -> {
if (name != null && !name.isEmpty()) {
return cb.like(root.get("name"), "%" + name + "%");
}
return null;
};
return userRepository.findAll(spec, pageable);
}
}
完整示例 - REST API
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// GET /api/users?page=1&size=10
@GetMapping
public ResponseEntity<PageResult<User>> getUsers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String name) {
PageResult<User> result = userService.getUsersByPage(page, size, name);
return ResponseEntity.ok(result);
}
// GET /api/users/page?page=1&size=10&sort=id,desc
@GetMapping("/page")
public ResponseEntity<Page<User>> getUsersWithSort(
@PageableDefault(page = 0, size = 10, sort = "id", direction = Sort.Direction.DESC)
Pageable pageable) {
Page<User> users = userService.findAll(pageable);
return ResponseEntity.ok(users);
}
}
分页查询最佳实践
统一分页响应格式
public class ApiResponse<T> {
private int code;
private String message;
private PageResult<T> data;
// 静态工厂方法
public static <T> ApiResponse<T> success(PageResult<T> data) {
ApiResponse<T> response = new ApiResponse<>();
response.setCode(200);
response.setMessage("success");
response.setData(data);
return response;
}
}
分页参数校验
@Component
public class PageRequestValidator {
public void validate(PageRequest pageRequest) {
if (pageRequest.getPage() < 1) {
throw new IllegalArgumentException("页码必须大于0");
}
if (pageRequest.getSize() < 1 || pageRequest.getSize() > 100) {
throw new IllegalArgumentException("每页记录数必须在1-100之间");
}
}
}
这些示例覆盖了从简单到复杂的分页实现方式,您可以根据实际项目需求选择合适的方法,推荐在Spring Boot项目中使用MyBatis Plus或Spring Data JPA,它们提供了完善的分页支持。