springData JPA Specification的查询

我爱海鲸 2025-04-15 11:48:48 暂无标签

简介分页、jpa、in、时间查询、like、联合主键操作

分页查询:

Controller:

    @PostMapping("/page")
    public TestResponseModel page(@RequestBody TestQuery query, @PageableDefault Pageable pageable) {
        log.info("test-入参: query={}, pageable={}", query.toString(), pageable.toString());
        Page<TestPageVo> page = testService.findPage(query, pageable);
        return TestListResponseModel.success(page.getContent(), page.getTotalElements());
    }

service:

   public Page<TestPageVo> findPage(TestQuery query, Pageable pageable) {
        List<TestPageVo> vos = new ArrayList<>();
        String name = query.getName();
        List<TestPo> testPos = repository.findAllByName(name );
        List<Long> ids = testPos.stream().map(TestPo::getId).collect(Collectors.toList());
        query.seInIds(ids);
        Page<TestPo> pos = testRepository.findAll((Specification<TestPo>) (root, criteriaQuery, criteriaBuilder) -> queryCondition(query, root, criteriaBuilder), pageable);
        for (TestPo testPo: pos) {
            TestPageVo testPageVo = wrapperTestVo(testPo);
            vos.add(testVo);
        }
        long total = pos.getTotalElements();
        return new PageImpl<>(vos, pageable, total);
    }

wrapperTestVo:

    private TestVo wrapperTestVo(TestPo testPo ) {
        TestVo testVo = new TestVo ();
        // po转vo

        return testVo;
    }

queryCondition:(查询条件构造)

 public Predicate queryCondition(TestQuery query, Root<TestPo> root, CriteriaBuilder criteriaBuilder) {
        List<Predicate> predicateList = Lists.newArrayList();
        if (query != null) {
            if (query.getId() != null) {
                predicateList.add(criteriaBuilder.equal(root.get("id").as(Long.class), query.getId()));
            }
            if (StringUtils.isNotBlank(query.getAlarmName())) {
//                predicateList.add(criteriaBuilder.like(root.get("name").as(String.class), "%" + query.getName() + "%"));
                predicateList.add(criteriaBuilder.equal(root.get("name").as(String.class), query.getName()));
            }
            if (StringUtils.isNotBlank(query.getEmail())) {
                predicateList.add(criteriaBuilder.equal(root.get("email").as(String.class), query.getEmail()));
            }
            if (StringUtils.isNotBlank(query.getPhone())) {
                predicateList.add(criteriaBuilder.equal(root.get("mobile").as(String.class), query.getPhone()));
            }
            if (!CollectionUtils.isEmpty(query.getInIds())) {
                Predicate predicate = root.get("inId").in(query.getInIds());
                predicateList.add(predicate);
            }
        }
        Predicate[] p = new Predicate[predicateList.size()];
        return criteriaBuilder.and(predicateList.toArray(p));
    }

2025-04-14 start:

    public Predicate queryShowCondition(Root<AnnouncementPo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        List<Predicate> predicateList = new ArrayList<>();
        predicateList.add(cb.equal(root.get("isTop"), 1));
        predicateList.add(cb.equal(root.get("status"), 1));
        predicateList.add(cb.lessThanOrEqualTo(root.get("publishTime"), new Date()));
        Predicate andPredicate = cb.and(predicateList.toArray(new Predicate[0]));
        Order orderByTop = cb.desc(root.get("isTop"));
        Order orderByPublishTime = cb.desc(root.get("publishTime"));
        query.where(andPredicate)
                .orderBy(orderByTop, orderByPublishTime);

        return andPredicate;
    }

end

TestQuery:(查询的实体对象)

@Data
@ToString
@Accessors(chain = true)
public class TestQuery {

    /**
     * 主键id
     */
    private Long id;

    /**
     * 名称
     */
    private String name;


    /**
     * 邮箱
     */
    private String email;

    /**
     * 手机号
     */
    private String phone;

    /**
     * inid
     */
    private List<Long> inIds;

}

2024-12-12 start:

public interface TestRepository extends JpaRepository<TestPo, Long>, JpaSpecificationExecutor<TestPo> {

}

end

2025-04-09 start

page 请求:localhost:8080/test/page?page=1&size=5&sort=createTime,desc

end

2025-04-15 start:

时间范围查询

public Predicate queryShowCondition(Root<AnnouncementPo> root, 
                                  CriteriaQuery<?> query, 
                                  CriteriaBuilder cb,
                                  Date startTime,  // 新增:开始时间参数
                                  Date endTime) {  // 新增:结束时间参数
    List<Predicate> predicateList = new ArrayList<>();
    
    // 原有条件:置顶、已发布、发布时间<=当前时间
    predicateList.add(cb.equal(root.get("isTop"), 1));
    predicateList.add(cb.equal(root.get("status"), 1));
    predicateList.add(cb.lessThanOrEqualTo(root.get("publishTime"), new Date()));
    
    // 新增时间范围条件(如果参数不为空)
    if (startTime != null) {
        // 发布时间 >= 开始时间
        predicateList.add(cb.greaterThanOrEqualTo(root.get("publishTime"), startTime));
    }
    if (endTime != null) {
        // 发布时间 <= 结束时间
        predicateList.add(cb.lessThanOrEqualTo(root.get("publishTime"), endTime));
    }
    
    // 组合所有条件用AND连接
    Predicate andPredicate = cb.and(predicateList.toArray(new Predicate[0]));
    
    // 排序条件:先按置顶降序,再按发布时间降序
    Order orderByTop = cb.desc(root.get("isTop"));
    Order orderByPublishTime = cb.desc(root.get("publishTime"));
    query.where(andPredicate)
         .orderBy(orderByTop, orderByPublishTime);

    return andPredicate;
}

jpa如果是联合主键时的操作

@Repository
public interface UserTestRepository extends JpaRepository<UserTestPo, UserTestIdPo> {
    /**
     * 检查用户是否测试过
     * @param userId 用户id
     * @param testId 测试id
     * @return ignore
     */
    boolean existsByUserIdAndTestId(String userId, Long testId);

    /**
     * 根据用户ID查找所有测试记录
     * @param userId 用户id
     * @return ignore
     */
    List<UserTestPo> findByUserId(String userId);

    /**
     * 根据测试ID查找所有阅读记录
     * @param testId 公告id
     * @return ignore
     */
    List<UserTestPo> findByTestId(Long testId);

    /**
     * 根据测试id删除中间表记录
     * @param testId 测试id
     * @return ignore
     */
    int deleteByTestId(Long testId);
}

UserTestIdPo:

@Data
@EqualsAndHashCode
public class UserTestIdPo implements Serializable {
    /**
     * 用户id
     */
    private String userId;

    /**
     * 测试id
     */
    private Long testId;
}

UserTestPo:

@Entity
@Table(name = "t_user_test")
@IdClass(UserTestIdPo.class)
@Data
public class UserTestPo {

    @Id
    @Column(name = "user_id", nullable = false)
    private String userId;

    @Id
    @Column(name = "test_id", nullable = false)
    private Long testId;

    @Column(name = "read_time")
    @Temporal(TemporalType.TIMESTAMP)
    private Date readTime;

}

end

你好:我的2025