You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将指定SQL查询转换为基于CriteriaBuilder的Hibernate CriteriaQuery

JPA CriteriaBuilder 实现对应SQL查询方案

实现前提

  • 已正确引入JPA相关依赖,可正常获取EntityManager实例
  • 涉及的User、Teacher、Book实体类已完成JPA字段映射

完整实现代码

场景1:实体类已配置关联注解

如果User实体已通过JPA注解配置了和Teacher、Book的关联关系,直接使用如下代码:

import javax.persistence.EntityManager;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

public List<User> queryUserList(Long collegeId, String subCode, String lang) {
    // 获取CriteriaBuilder实例
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    // 定义查询返回类型为User
    CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
    Root<User> userRoot = criteriaQuery.from(User.class);

    // 内连接关联Teacher表 对应SQL里的INNER JOIN Teacher t ON t.emp_id = u.emp_id
    Join<User, Teacher> teacherJoin = userRoot.join("empId", JoinType.INNER);
    // 内连接关联User关联的Book表
    Join<User, Book> bookJoin = userRoot.join("book", JoinType.INNER);

    // 组装查询条件
    List<Predicate> conditionList = new ArrayList<>();
    // 对应u.college_id=:college_id
    conditionList.add(criteriaBuilder.equal(userRoot.get("collegeId"), collegeId));
    // 对应u.Book.sub_code=:sub_code
    conditionList.add(criteriaBuilder.equal(bookJoin.get("subCode"), subCode));
    // 对应t.lang=:lang
    conditionList.add(criteriaBuilder.equal(teacherJoin.get("lang"), lang));

    // 组装查询语句
    criteriaQuery.select(userRoot)
            .where(conditionList.toArray(new Predicate[0]));

    // 执行查询返回结果
    return entityManager.createQuery(criteriaQuery).getResultList();
}

场景2:实体类未配置关联注解

如果User和Teacher是独立实体,没有配置关联注解,手动指定关联条件即可:

import javax.persistence.EntityManager;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

public List<User> queryUserList(Long collegeId, String subCode, String lang) {
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
    // 同时加载两个根实体
    Root<User> userRoot = criteriaQuery.from(User.class);
    Root<Teacher> teacherRoot = criteriaQuery.from(Teacher.class);
    Join<User, Book> bookJoin = userRoot.join("book", JoinType.INNER);

    List<Predicate> conditionList = new ArrayList<>();
    // 手动指定关联条件 对应ON t.emp_id = u.emp_id
    conditionList.add(criteriaBuilder.equal(userRoot.get("empId"), teacherRoot.get("empId")));
    // 其余查询条件和场景1一致
    conditionList.add(criteriaBuilder.equal(userRoot.get("collegeId"), collegeId));
    conditionList.add(criteriaBuilder.equal(bookJoin.get("subCode"), subCode));
    conditionList.add(criteriaBuilder.equal(teacherRoot.get("lang"), lang));

    criteriaQuery.select(userRoot)
            .where(conditionList.toArray(new Predicate[0]));

    return entityManager.createQuery(criteriaQuery).getResultList();
}

注意事项

  • 所有get("字段名")方法传入的是Java实体类的属性名,不是数据库表的列名,需和你自己实体类的定义保持一致
  • 推荐使用JPA静态元模型替换硬编码的字段名,比如将userRoot.get("collegeId")改成userRoot.get(User_.collegeId),可在编译期就校验字段正确性
  • 如果需要返回多表全部字段而非仅User实体,只需要将CriteriaQuery的泛型改为Object[],在select方法中传入需要返回的所有字段即可

内容的提问来源于stack exchange,提问作者Ganesh Prajapati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 02:48:03