如何使用Criteria API编写= ANY(?1)查询表达式?
PostgreSQL下用Criteria API实现= ANY(数组)的方案
JPA规范里的CriteriaBuilder#any()方法确实仅支持传入子查询作为参数,要实现传入自定义值数组匹配的需求,需要借助PostgreSQL方言的函数支持,以下是可直接落地的实现方式:
实现代码
核心逻辑(基于JPA标准API,兼容所有JPA实现)
// 已预先初始化好基础对象 CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<MyTableDTO> query = cb.createQuery(MyTableDTO.class); Root<MyTable> root = query.from(MyTable.class); // 1. 定义数组参数,类型和数据库字段e的类型保持一致 ParameterExpression<String[]> propArrayParam = cb.parameter(String[].class, "propArray"); // 2. 调用PostgreSQL原生的any函数,将数组作为参数传入 Expression<String> anyExpr = cb.function("any", String.class, propArrayParam); // 3. 构造等于谓词,对应SQL的t.e = ANY(?1) Predicate matchPredicate = cb.equal(root.get("e"), anyExpr); // 组装查询字段和条件 query.select(cb.construct( MyTableDTO.class, root.get("a"), root.get("b"), root.get("c") )).where(matchPredicate); // 执行查询时传入实际数组值 TypedQuery<MyTableDTO> typedQuery = entityManager.createQuery(query); typedQuery.setParameter("propArray", new String[]{"prop1", "prop2", "prop3"}); List<MyTableDTO> result = typedQuery.getResultList();
注意事项
- 需使用PostgreSQL官方对应版本的方言类,例如Hibernate下配置
hibernate.dialect=org.hibernate.dialect.PostgreSQL14Dialect(替换为你的数据库对应版本) - 数组参数的类型必须和数据库字段
e的类型严格匹配:如e是int类型,参数要定义为ParameterExpression<Integer[]>,避免出现类型不匹配的SQL报错 - Hibernate 6+版本对PostgreSQL数组做了原生优化,也可以直接用
in谓词实现:root.get("e").in(new String[]{"prop1", "prop2", "prop3"}),框架会自动生成= ANY(array[...])格式的SQL
内容的提问来源于stack exchange,提问作者miroana
相关产品推荐
相关产品推荐

