最近在接手一个项目,用的是JPA,以前没使用过。在开发新的需求过程中,发现有查询部分字段的情况,网上逛了半天,发现都是抄来抄去的"古文"。于是用英文搜索了下,总结了以下几点。
版本信息:Spring Boot 2.3.7
-
不需要新建Entity,但是需要一个所有部分字段的构造函数。当然如果你觉得返回的Entity中包含大量null值字段,以及多一个所有部分字段的构造函数不妥,也可以新建一个子集Entity。
-
不使用findAll,而是使用EntityManager来执行CriteriaQuery.multiselect的查询。
-
没有用@Query,因为我的查询是动态的。
-
也可以支持分页。
示例代码,用模糊查询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);
}