返回Optional<T>的JPQL查询如何用CriteriaBuilder正确实现?
正确CriteriaBuilder实现方案
原有代码问题梳理
- 方法名笔误:原需求是实现手机号查询逻辑,你写的方法名
findByCreatedDate和功能不匹配 - 冗余排序逻辑:原JPQL查询没有指定排序规则,代码中额外添加的
orderBy属于无效冗余逻辑 - 结果取值逻辑错误:直接调用
getResultList().get(3)存在两个风险:一是查询结果总数不足4条时直接抛出索引越界异常;二是返回值为UserDetail类型,和要求的Optional<UserDetail>返回类型不匹配 - 空结果场景未兼容:JPA原生查询无匹配结果时调用
getSingleResult会抛出NoResultException,需要手动捕获处理包装为空Optional
正确实现代码
import javax.persistence.NoResultException; import org.springframework.transaction.annotation.Transactional; // 修正方法名和业务功能匹配 @Override @Transactional(readOnly = true) public Optional<UserDetail> findByPhoneNumber(String phoneNumber) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<UserDetail> cq = cb.createQuery(UserDetail.class); Root<UserDetail> root = cq.from(UserDetail.class); // 拼接查询条件,和原JPQL逻辑完全对齐 cq.where(cb.equal(root.get("phoneNumber"), phoneNumber)); try { UserDetail result = em.createQuery(cq).getSingleResult(); return Optional.ofNullable(result); } catch (NoResultException e) { // 无匹配结果时返回空Optional,和原JPQL返回逻辑一致 return Optional.empty(); } }
可选优化
如果你的业务场景允许同一个手机号对应多条UserDetail记录,可添加分页限制避免抛出NonUniqueResultException:
UserDetail result = em.createQuery(cq) // 仅取第一条匹配结果 .setMaxResults(1) .getSingleResult();
内容的提问来源于stack exchange,提问作者iwritecomeinmymind
相关产品推荐
相关产品推荐

