学习进度条

每日总结(SpringBoot 条件查询专题)

今日学习时间:1小时
今日代码量:100行
今日博客:1篇(SpringBoot JPA 条件查询的5种实现方式


1. JPA 方法命名查询(无需SQL)

// 1. 按名称精确查询
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByUsername(String username);
    
    // 2. 多条件AND查询
    List<User> findByUsernameAndAgeGreaterThan(String username, int age);
    
    // 3. 模糊查询 + 排序
    List<User> findByUsernameContainingOrderByCreateTimeDesc(String keyword);
}

2. @Query 注解(JPQL)

// 4. JPQL条件查询
@Query("SELECT u FROM User u WHERE u.age BETWEEN :min AND :max")
List<User> findUsersByAgeRange(@Param("min") int minAge, 
                              @Param("max") int maxAge);

// 5. 原生SQL查询
@Query(value = "SELECT * FROM users WHERE status = :status", nativeQuery = true)
List<User> findByStatus(@Param("status") int status);

3. Specification 动态条件(JPA Criteria)

// 6. 构建动态条件
public class UserSpecs {
    public static Specification<User> hasUsername(String username) {
        return (root, query, cb) -> 
            username == null ? null : cb.equal(root.get("username"), username);
    }
    
    public static Specification<User> ageGreaterThan(int age) {
        return (root, query, cb) -> 
            cb.greaterThan(root.get("age"), age);
    }
}

// 使用示例
List<User> users = userRepository.findAll(
    Specification.where(UserSpecs.hasUsername("张三"))
        .and(UserSpecs.ageGreaterThan(18))
);

4. QueryDSL 类型安全查询

// 7. QueryDSL条件组合
public List<User> searchUsers(String username, Integer minAge) {
    QUser user = QUser.user;
    BooleanBuilder builder = new BooleanBuilder();
    
    if (StringUtils.isNotBlank(username)) {
        builder.and(user.username.contains(username));
    }
    if (minAge != null) {
        builder.and(user.age.goe(minAge));
    }
    
    return queryFactory.selectFrom(user)
                      .where(builder)
                      .fetch();
}

5. MyBatis 动态SQL(XML方式)

<!-- 8. MyBatis条件查询 -->
<select id="findByCondition" resultType="User">
    SELECT * FROM users
    <where>
        <if test="username != null">
            AND username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="minAge != null">
            AND age >= #{minAge}
        </if>
    </where>
    ORDER BY id DESC
</select>

实践案例

// 综合示例:分页条件查询
@GetMapping("/users")
public Page<User> queryUsers(
    @RequestParam(required = false) String username,
    @RequestParam(defaultValue = "0") int minAge,
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "10") int size) {
    
    return userRepository.findAll(
        (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotBlank(username)) {
                predicates.add(cb.like(root.get("username"), "%" + username + "%"));
            }
            if (minAge > 0) {
                predicates.add(cb.ge(root.get("age"), minAge));
            }
            return cb.and(predicates.toArray(new Predicate[0]));
        },
        PageRequest.of(page, size, Sort.by("createTime").descending())
    );
}

关键收获

  1. 掌握了5种条件查询的实现方式及适用场景
  2. 理解了动态条件拼接的Specification原理
  3. 实现了带分页的复合条件查询接口

遇到的问题

  • JPA方法名解析失败(解决:检查命名是否符合规范)
  • QueryDSL的QClass未生成(解决:执行mvn compile生成)
posted @ 2025-04-14 19:34  haoyinuo  阅读(9)  评论(0)    收藏  举报