spring data jpa specification实现复杂查询
持久化API概述:
1、JPA持久化API主要如下:
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID>
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
public interface JpaRepositoryImplementation<T, ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T>
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID>
2、JpaRepository 接口拥有常用的 CURD 方法以及分页方法、字段排序等操作,
但是没有与或非、like、以及大于等于、小于等于等操作,
这些方法都在 JpaSpecificationExecutor 接口中。
3、如果只需要简单的实现 CRUD、分页、排序,则继承 JpaRepository接口即可,
如果还需要复杂查询,则可以再继承 JpaSpecificationExecutor 接口,也可以直接继承 JpaRepositoryImplementation 接口
JpaSpecificationExecutor 中 API:
List<T>findAll(@Nullable Specification<T> spec) | 规范查询,没有数据时返回空列表。 |
Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable) | 规范查询,同时进行分页查询。 |
List<T> findAll(@Nullable Specification<T> spec, Sort sort) | 规范查询,同时指定排序字段。 |
Optional<T> findOne(@Nullable Specification<T> spec) | 规范查询单条数据,注意如果结果多余一条,则抛异常。 |
long count(@Nullable Specification<T> spec) | 规范查询,返回查询到的记录数 |
JPA Specification构建 (匿名内部类实现)
1.条件查询
Specification specification = new Specification<TV>() {
@Override
public Predicate toPredicate(Root<TV> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicateList = new ArrayList<>();
//条件1:查询 tvName 为 海信 的数据,root.get 中的值与 TV 实体中的属性名称对应
predicateList.add(cb.equal(root.get("tvName").as(String.class), tvName));
//条件2:TV 生产日期(dateOfProduction)大于等于 start 的数据
predicateList.add(cb.greaterThanOrEqualTo(root.get("dateOfProduction").as(Date.class), start));
//条件3:TV 生产日期(dateOfProduction)小于等于 end 的数据
predicateList.add(cb.lessThanOrEqualTo(root.get("dateOfProduction").as(Date.class), end));
Predicate[] pre = new Predicate[predicateList.size()];
pre = predicateList.toArray(pre);
return query.where(pre).getRestriction();
}
};
2.模糊查询
Specification<TV> tvSpecification = new Specification<TV>() {
@Override
public Predicate toPredicate(Root<TV> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate[] predicates = new Predicate[1];
predicates[0] = cb.like(root.get("tvName").as(String.class), "%" + tvNameLike + "%");
return query.where(predicates).getRestriction();
}
};
3.查询并排序
tvRepository.findAll(tvSpecification, Sort.by(Sort.Direction.DESC, "tvId"))
4.分页查询
//可以使用重载的 of(int page, int size, Sort sort) 方法指定排序字段
Pageable pageable = PageRequest.of(page, size)
page:第几页
size:数量大小
注:以上蓝色字段为传参
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App