JPA 标准 API 和 Oracle JSON_TABLE 函数

Posted

技术标签:

【中文标题】JPA 标准 API 和 Oracle JSON_TABLE 函数【英文标题】:JPA Criteria API and Oracle JSON_TABLE function 【发布时间】:2020-11-23 13:11:42 【问题描述】:

我在java中基于sql代码编写条件有问题,我们必须使用JSON_TABLE函数并按参数搜索:

    select tab1.id
         from TABLE1 tab1
                  left join
              TABLE2 param_json on tab1.id = param_json.TABLE_1_ID,
              json_table(
                         param_json.PARAMS_JSON, '$[*]'
                         COLUMNS (
                             "paramCode" VARCHAR2(4000) PATH '$.paramCode',
                             "displayValue" VARCHAR2(4000) PATH '$.displayValue'
                             )
              ) jt
         where jt."paramCode" = 'param1' and lower(jt."displayValue") like '%value%');
    CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<Long> query = builder.createQuery(Long.class);
    Root<Table1> table1Root = query.from(Table1.class);
    Join<Table1, Table2> jsonEJBJoin = table1Root.join(Table1_.table2Elements);
    
    //how add json_table function
    
    List<Predicate> whereConditions = new LinkedList<>();
    Predicate[] predicates = new Predicate[whereConditions.size()];
    
    //how add where conditions based on json_table function
    
     query.where(whereConditions.toArray(predicates));
     query.select(table1Root.get(Table1_.id));
    
      List<Long> resultList = getEntityManager().createQuery(query)
                    .setMaxResults(10)
                    .getResultList();

【问题讨论】:

您已经添加了一个 SQL 查询和一些 Java 代码,但没有描述实际无法正常工作的内容。你想达到什么目标,什么是行不通的? criteria api 必须生成与上面相同的查询,json_table 是 oracle 特定的函数,我不知道如何在 Criteria API 中使用它 【参考方案1】:

这很难,因为您将螺丝刀用作锤子。 Criteria API 的全部意义在于拥有独立于平台的代码,它不依赖于像json_table 这样的专有函数。

如果您有数据库访问权限,我认为解决此问题的最简洁方法是创建一个视图以隐藏 JPA 中的所有 Oracle 特定代码,例如:

create or replace view VIEW1 (TABLE_1_ID, PARAMCODE, DISPLAYVALUE) as
    select param_json.TABLE_1_ID, jt.paramCode, jt.displayValue
    from TABLE2 param_json,
      json_table(
                 param_json.PARAMS_JSON, '$[*]'
                 COLUMNS (
                     paramCode VARCHAR2(4000) PATH '$.paramCode',
                     displayValue VARCHAR2(4000) PATH '$.displayValue'
                     )
      ) jt;

然后将 JPA 代码中的 Table2 替换为 View1。

如果您无法修改数据库,我认为您将不得不放弃 Criteria API 并使用带有绑定变量参数的 NativeQuery,例如:

List<Long> resultList = getEntityManager().createNativeQuery("select tab1.id
     from TABLE1 tab1
              left join
          TABLE2 param_json on tab1.id = param_json.TABLE_1_ID,
          json_table(
                     param_json.PARAMS_JSON, '$[*]'
                     COLUMNS (
                         paramCode VARCHAR2(4000) PATH '$.paramCode',
                         displayValue VARCHAR2(4000) PATH '$.displayValue'
                         )
          ) jt
        where jt.paramCode = :param1 and lower(jt.displayValue) like :param2))" )
    .setParameter("param1", param1)
    .setParameter("param2", "%" + value + "%" )
    .setMaxResults(10)
    .getResultList();

作为旁注,我建议不要使用区分大小写的 Oracle 标识符(带双引号)。一些 Oracle 教程使用它们,但它们只会使事情变得更复杂。

【讨论】:

以上是关于JPA 标准 API 和 Oracle JSON_TABLE 函数的主要内容,如果未能解决你的问题,请参考以下文章

JPA命名查询与标准API?

多对一的 JPA 标准 API 规范

Jpa 重写方言dialect 使用oracle / mysql 数据库自定义函数

JPA 2.0、标准 API、子查询、表达式中

如何为以下语句编写标准构建器 API JPA 查询

具有多个参数的 JPA 标准 API