前几天 使用 jpa 连接 pg 库来开发一个模块 发现这个玩意 平时挺好用 但是涉及到一些复杂一点的动态查询 咱也不多说直接上 代码 然后一点点 解释
首先 使用jpa 的dao层都需要 去继承一个接口来实现curd
第一步 省略。。 创建一个 model
第二步 dao层
public interface OperatorDao extends JpaRepository<OperatorPO, String>, JpaSpecificationExecutor<OperatorPO> {
// 这里就不多说了 类似 mybatisplus 但是 JpaSpecificationExecutor 这个 方法很重要因为 他里面 包含的
/**
Optional<T> findOne(@Nullable Specification<T> var1);
List<T> findAll(@Nullable Specification<T> var1);
Page<T> findAll(@Nullable Specification<T> var1, Pageable var2);
List<T> findAll(@Nullable Specification<T> var1, var2);
long count(@Nullable Specification<T> var1);
*/
// 这些方法 其中 Specification 这个参数 就是我们要实现动态查询 类 而 Pageable Sort 这两个不用过多
// 介绍 一看就知道一个是排序 一个 是分页
}
第三步 service 层
```java
//OperatorPO 这个就是 你创建的model 也就是表 映射的类
public Page<OperatorPO> search(SearchVO searchVO) {
//动态查询
Specification<OperatorPO> sf = (Specification<OperatorPO>) (root, query, cb) -> {
//用于添加所有查询条件 如果 使用过es 查询 的人可以很好理解 这里 分层去封装每个层级是事情
/* 这里使用 java lambda 表达式来创建 如果 使用不习惯可一个去实现类去写
root, 者根就是你表的数据
query, 就是查询外层的 条件了 where
cb 就是你要操作的类型 相等 模糊或者 范围
*/
List<Predicate> p = new ArrayList<>();
if (StringUtils.isNotBlank(searchVO."传入的字段1")) {
Predicate p5 = cb.equal(root.get("表的字段1").as(String.class), searchVO."传入的字段1");
p.add(p5);
}
if (StringUtils.isNotBlank(searchVO."传入的字段2")) {
Predicate p1 = cb.like(root.get("表的字段2").as(String.class), "%"+searchVO."传入的字段2"+"%");
p.add(p1);
}
if (StringUtils.isNotBlank(searchVO."传入的开始时间") && StringUtils.isNotBlank(searchVO."传入的开始结束")) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date start = simpleDateFormat.parse(searchVO."传入的开始时间");
Date end = simpleDateFormat.parse(searchVO."传入的开始结束");
Predicate p3 = cb.greaterThanOrEqualTo(root.get("表的时间").as(Date.class), start);
Predicate p4 = cb.lessThanOrEqualTo(root.get("表的时间").as(Date.class), end);
p.add(p3);
p.add(p4);
} catch (ParseException e) {
e.printStackTrace();
}
}
Predicate[] pre = new Predicate[p.size()];
// 决定了 每个 操作之间 关系 是并且还是或
Predicate and = cb.and(p.toArray(pre)); //查询条件 and
//Predicate or = cb.or(p.toArray(pre)); //查询条件 or
query.where(and); //添加查询条件
// 返回 这个对象
return query.getRestriction();
};
// 分页操作
Integer pageNo = searchVO.getPageNo();
Integer pageSize = searchVO.getRow();
List<Sort.Order> orders = new ArrayList<>();
orders.add(new Sort.Order(Sort.Direction.DESC, "表要排序的字段"));
// 排序
Sort by = Sort.by(orders);
// 分页
PageRequest pageRequest = PageRequest.of((pageNo - 1), pageSize, by);
// 这里是将所有的 条件添加到查询 里面 搜索
Page<OperatorLogPO> all = operatorDao.findAll(sf, pageRequest);
return all;
}
第四部 获取
Page<OperatorPO> oS = 这里就调用第二步的方法
// 获取 查询到的总是
long totalElements = oS .getTotalElements();
// 获取到 数据流
Stream<OperatorPO> POStream = oS .get();
// 转化为 集合
List<OperatorPO> collect = POStream.collect(Collectors.toList());