spring data jpa复杂多条件查询
一.排序与分页 // 排序 Direction direction = Direction.DESC; //directionStr为前端传值,asc代表正序 if ("asc".equals(directionStr)) { direction = Direction.ASC; } //默认使用datetime字段进行排序 String sortProperty = "datetime"; //sortParam为前端传的排序字段 if (UtilValidate.isNotEmpty(sortParam)) { sortProperty = sortParam; } Sort sort = new Sort(direction,sortProperty); // 分页 // pageNumParam为页码,默认为0,pageSizeParam为每页条数 Pageable pageable = PageRequest.of(pageNumParam,pageSizeParam,sort); 注意: 如果想要按照外键关联实体的某个属性进行排序,sortProperty直接改为对应的 “实体名.属性名” 即可: 1.比如一个User实体对象,外键一对一关联地址实体对象Address,如果希望可以通过地址对象的id字段排序,那么sortProperty就应该传 “address.id” 。 @Entity @Table(name="t_user") public class User{ @Id private Long id; @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name = "address_id") @NotFound(action=NotFoundAction.IGNORE) private Address address; /** * 登录名 */ @Column private String username; /** * 状态 */ @Column private Integer state; /** * 所属机构 */ @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name = "department_id") @NotFound(action=NotFoundAction.IGNORE) private Department department; /** * 注册时间 */ @Column private Long datetime; } 2.项目使用的是oracle数据库,使用这种写法刚开始一直报错,排查后发现是配置的oracle方言的问题,如果有同样使用oracle数据库的小伙伴需要注意下,以下是修改的相关配置项: #spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.OracleDialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle9Dialect 二.复杂查询 以下的复杂查询包含了4种类型: 1.外键关联查询 — 标注1 2.或查询 — 标注2 3.外键in查询 — 标注3 4.id的in查询 — 标注4 使用JPA进行复杂多条件查询,一般都需要重写JpaSpecificationExecutor接口中的方法: public interface JpaSpecificationExecutor<T> { T findOne(Specification<T> spec); List<T> findAll(Specification<T> spec); Page<T> findAll(Specification<T> spec,Pageable pageable); List<T> findAll(Specification<T> spec,Sort sort); long count(Specification<T> spec); } 我们此处需要使用的是Page findAll(Specification spec,Pageable pageable)方法,所以要针对它进行重写: // 假设此处查询的是用户列表 return userRepository.findAll(new Specification() { @Override public Predicate toPredicate(Root root,CriteriaQuery query,CriteriaBuilder cb) { List<Predicate> pList = new ArrayList<Predicate>(); Predicate[] ps = new Predicate[pList.size()]; List<Predicate> stateList = new ArrayList<Predicate>(); Predicate[] statePs = new Predicate[stateList.size()]; // 查询用户表中未删除的地址 (标注1) // 假设address是用户表User中的外键关联,存放地址信息,state为0代表有效 pList.add(cb.equal(root.join("address").get("state"),0)); //查询状态为10-未审核或0-已审核状态的用户 (标注2) stateList.add(cb.equal(root.get("state"),0)); stateList.add(cb.equal(root.get("state"),10)); pList.add(cb.or(stateList.toArray(statePs))); // 时间查询 pList.add(cb.between(root.get("datetime"),start,end)); // 机构查询 (标注3) if (UtilValidate.isNotEmpty(departsStr)) { Predicate pDepart = inQuery(departsStr,"department",cb,root); pList.add(pDepart); } query.where(pList.toArray(ps)); return null; } },pageable); 以下为使用到的外键关联in查询的方法: public Predicate inQuery(String entityIds,String entityName,CriteriaBuilder cb,Root root) { List<Predicate> list = new ArrayList<>(); String[] ids = entityIds.split(","); if (ids != null && ids.length > 0) { In<Object> in = cb.in(root.join(entityName).get("id")); for (String id : ids) { Long idNum = Long.parseLong(id); in.value(idNum); } list.add(in); } Predicate[] p = new Predicate[list.size()]; return cb.and(list.toArray(p)); } 如果希望进行id的in查询,只需把root.join(entityName).get(“id”)改为root.get(“id”)即可(标注4)。 (编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |