如何用Java案例实现数据分页查询?

wen java案例 6

本文目录导读:

如何用Java案例实现数据分页查询?

  1. 基础分页实现(手动计算)
  2. JDBC实现分页
  3. MyBatis Plus分页
  4. Spring Data JPA分页
  5. 完整示例 - REST API
  6. 分页查询最佳实践

我来为您详细介绍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,它们提供了完善的分页支持。

抱歉,评论功能暂时关闭!