JPA查询部分字段的最佳实践

最近在接手一个项目,用的是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);
}
相关推荐
后端AI实验室1 小时前
我把一个生产Bug的排查过程,交给AI处理——20分钟后我关掉了它
java·ai
凉年技术3 小时前
Java 实现企业微信扫码登录
java·企业微信
狂奔小菜鸡4 小时前
Day41 | Java中的锁分类
java·后端·java ee
hooknum5 小时前
学习记录:基于JWT简单实现登录认证功能-demo
java
程序员Terry5 小时前
同事被深拷贝坑了3小时,我教他原型模式的正确打开方式
java·设计模式
NE_STOP5 小时前
MyBatis-缓存与注解式开发
java
码路飞5 小时前
不装 OpenClaw,我用 30 行 Python 搞了个 QQ AI 机器人
java
Re_zero6 小时前
以为用了 try-with-resources 就稳了?这三个底层漏洞让TCP双向通讯直接卡死
java·后端
SimonKing6 小时前
Fiddler抓包完全指南:从安装配置到抓包,一文讲透
java·后端·程序员
磊磊落落7 小时前
如何将 Spring Statemachine 作为一个轻量级工作流引擎来使用?
java