Spring Data JPA如何基于字段值过滤返回数据并按指定字段排序
Spring JPA 实现指定条件查询的方案
以下是3种无需编写原生SQL的常用实现方案,均基于你提供的Car实体类实现:
方案1:方法名派生查询(无需手动编写查询语句)
Spring Data JPA 支持按照既定规则定义接口方法,框架会自动解析生成对应SQL。
首先定义CarRepository接口继承JpaRepository:
import org.springframework.data.jpa.repository.JpaRepository; import java.time.LocalDate; import java.util.List; public interface CarRepository extends JpaRepository<Car, Long> { // 方法名按规则拼接,自动解析为符合要求的查询 List<Car> findByAccidentDateIsNullAndBuyDateGreaterThanEqualOrderByCarNumberAsc(LocalDate currentDate); }
调用时直接传入当前日期即可:
// 调用示例 List<Car> validCars = carRepository.findByAccidentDateIsNullAndBuyDateGreaterThanEqualOrderByCarNumberAsc(LocalDate.now());
方案2:JPQL 查询(语法灵活,避免过长方法名)
如果觉得方法名过长可读性差,可以用@Query注解写JPQL语句实现,还可以直接调用JPQL内置的CURRENT_DATE函数,不需要手动传日期参数:
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; public interface CarRepository extends JpaRepository<Car, Long> { @Query("SELECT c FROM Car c WHERE c.accidentDate IS NULL AND c.buyDate >= CURRENT_DATE ORDER BY c.carNumber ASC") List<Car> findValidCars(); }
直接调用findValidCars()方法即可获取符合条件的结果。
注:如果你需要沿用之前JDBC示例中的
OR条件,只需要把上述JPQL中的AND改成OR即可,方法名派生查询则把方法名中的And替换为Or。
方案3:Specification 动态查询(适合条件动态变化的场景)
如果后续查询条件需要动态拼接,推荐用JPA Specification实现:
首先让CarRepository同时继承JpaSpecificationExecutor接口:
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; public interface CarRepository extends JpaRepository<Car, Long>, JpaSpecificationExecutor<Car> { }
构造查询条件调用即可:
import org.springframework.data.jpa.domain.Specification; import jakarta.persistence.criteria.Predicate; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; // 业务逻辑层调用代码 Specification<Car> spec = (root, query, cb) -> { List<Predicate> predicates = new ArrayList<>(); // 添加ACCIDENT_DATE为NULL的条件 predicates.add(cb.isNull(root.get("accidentDate"))); // 添加BUY_DATE大于等于当前日期的条件 predicates.add(cb.greaterThanOrEqualTo(root.get("buyDate"), LocalDate.now())); // 按CAR_NUMBER升序排序 query.orderBy(cb.asc(root.get("carNumber"))); return cb.and(predicates.toArray(new Predicate[0])); }; List<Car> validCars = carRepository.findAll(spec);
注意:如果实体类属性名和数据库字段名不是默认驼峰转下划线的映射规则,需要在对应属性上添加
@Column(name = "数据库实际字段名")手动指定映射关系。
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

