最近在接手一个项目,用的是JPA,以前没使用过。在开发新的需求过程中,发现有查询部分字段的情况,网上逛了半天,发现都是抄来抄去的“古文”。于是用英文搜索了下,总结了以下几点。
版本信息:Spring Boot 2.3.7
1. 不需要新建Entity,但是需要一个所有部分字段的构造函数。当然如果你觉得返回的Entity中包含大量null值字段,以及多一个所有部分字段的构造函数不妥,也可以新建一个子集Entity。
2. 不使用findAll,而是使用EntityManager来执行CriteriaQuery.multiselect的查询。
3. 没有用@Query,因为我的查询是动态的。
4. 也可以支持分页。
示例代码,用模糊查询Merchant的部分字段,并要求分页。
(不过,总觉得这些代码有些冗余,不知道有没有其它更优的写法)
public Page<Merchant> listMerchant(String name, Pageable pageable) {CriteriaBuilder totalRowsCb = this.entityManager.getCriteriaBuilder();CriteriaQuery<Long> totalRowsQuery = totalRowsCb.createQuery(Long.class);Root<Merchant> totalRowsRoot = totalRowsQuery.from(Merchant.class);totalRowsQuery.where(totalRowsCb.like(totalRowsRoot.get("name"), "%" + name + "%"));totalRowsQuery.select(totalRowsCb.count(totalRowsRoot));Long totalRows = entityManager.createQuery(totalRowsQuery).getSingleResult();CriteriaBuilder listCb = this.entityManager.getCriteriaBuilder();CriteriaQuery<Merchant> listQuery = listCb.createQuery(Merchant.class);Root<Merchant> listRoot = listQuery.from(Merchant.class);List<Order> orderList = QueryUtils.toOrders(pageable.getSort(), listRoot, listCb);listQuery .multiselect(listRoot.get("mid").alias("mid"),listRoot.get("name").alias("name"),listRoot.get("businessName").alias("businessName"),listRoot.get("contactEmail").alias("contactEmail"),listRoot.get("status").alias("status"),listRoot.get("accountStatus").alias("accountStatus")).where(listCb.like(listRoot.get("name"), "%" + name + "%")).orderBy(orderList);List<Merchant> merchantList = entityManager.createQuery(listQuery).setMaxResults(pageable.getPageSize()).setFirstResult((int)pageable.getOffset()).getResultList();return new PageImpl<>(merchantList, pageable, totalRows);
}