基于多可选参数的Spring Data JPA分页搜索功能实现求助
基于可选参数的分页搜索实现方案
先纠正实体类的关键问题
你的UserDetails实体类将age设为主键不合理,会导致同年龄用户主键冲突,建议修改为独立自增主键:
@Entity @Table(name = "userDetails") public class UserDetails { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; // 新增独立主键字段 private int age; private String manglik; private String maritalStatus; private String manglikStatus; private String religion; private String caste; private String location; // 省略getter、setter、构造方法 }
实现步骤
1. 创建搜索参数DTO
定义一个DTO接收前端的可选搜索参数和分页参数:
public class UserSearchCriteria { private Integer age; private String manglik; private String maritalStatus; private String manglikStatus; private String religion; private String caste; private String location; // 分页默认参数 private int page = 0; private int size = 10; private String sortBy = "id"; private String sortDir = "asc"; // 省略getter、setter }
2. 编写动态查询Specification
利用Specification接口动态拼接非空参数的查询条件:
import org.springframework.data.jpa.domain.Specification; import jakarta.persistence.criteria.Predicate; import java.util.ArrayList; import java.util.List; public class UserDetailsSpecification { public static Specification<UserDetails> getSpecification(UserSearchCriteria criteria) { return (root, query, criteriaBuilder) -> { List<Predicate> predicates = new ArrayList<>(); if (criteria.getAge() != null) { predicates.add(criteriaBuilder.equal(root.get("age"), criteria.getAge())); } if (criteria.getManglik() != null && !criteria.getManglik().isEmpty()) { predicates.add(criteriaBuilder.equal(root.get("manglik"), criteria.getManglik())); } if (criteria.getMaritalStatus() != null && !criteria.getMaritalStatus().isEmpty()) { predicates.add(criteriaBuilder.equal(root.get("maritalStatus"), criteria.getMaritalStatus())); } if (criteria.getManglikStatus() != null && !criteria.getManglikStatus().isEmpty()) { predicates.add(criteriaBuilder.equal(root.get("manglikStatus"), criteria.getManglikStatus())); } if (criteria.getReligion() != null && !criteria.getReligion().isEmpty()) { predicates.add(criteriaBuilder.equal(root.get("religion"), criteria.getReligion())); } if (criteria.getCaste() != null && !criteria.getCaste().isEmpty()) { predicates.add(criteriaBuilder.equal(root.get("caste"), criteria.getCaste())); } if (criteria.getLocation() != null && !criteria.getLocation().isEmpty()) { predicates.add(criteriaBuilder.equal(root.get("location"), criteria.getLocation())); } return criteriaBuilder.and(predicates.toArray(new Predicate[0])); }; } }
3. Service层实现分页查询逻辑
注入Repository,封装分页和查询条件的调用:
import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; @Service public class UserDetailsService { private final UserDetailsRepository userDetailsRepository; public UserDetailsService(UserDetailsRepository userDetailsRepository) { this.userDetailsRepository = userDetailsRepository; } public Page<UserDetails> searchUsers(UserSearchCriteria criteria) { Sort sort = Sort.by(Sort.Direction.fromString(criteria.getSortDir()), criteria.getSortBy()); Pageable pageable = PageRequest.of(criteria.getPage(), criteria.getSize(), sort); Specification<UserDetails> spec = UserDetailsSpecification.getSpecification(criteria); return userDetailsRepository.findAll(spec, pageable); } }
4. Controller层接收请求并返回结果
通过@ModelAttribute接收参数,返回分页结果:
import org.springframework.data.domain.Page; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/users") public class UserDetailsController { private final UserDetailsService userDetailsService; public UserDetailsController(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } @GetMapping("/search") public ResponseEntity<Page<UserDetails>> searchUsers(@ModelAttribute UserSearchCriteria criteria) { Page<UserDetails> result = userDetailsService.searchUsers(criteria); return ResponseEntity.ok(result); } }
使用说明
前端可通过GET请求传递任意可选参数,例如:/users/search?age=28&religion=Hindu&page=1&size=15
未传递的参数不会加入查询条件,返回的Page对象包含总条数、总页数、当前页数据等完整分页信息。
内容的提问来源于stack exchange,提问作者Ravi
相关产品推荐
相关产品推荐

