0

I have a problem with writing criteria in java based on sql code, we must use JSON_TABLE function and search by parameters:

    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();
2
  • You have added a SQL query and some Java code but have not described what is not actually working properly. What are you trying to achieve and what is not working? Commented Nov 23, 2020 at 13:34
  • criteria api must generate same query as above, json_table is oracle specific function and i don't know how to use this in Criteria API Commented Nov 23, 2020 at 13:55

1 Answer 1

1

This is hard because you're using a screwdriver as a hammer. The whole point of the Criteria API is to have platform-independent code which doesn't depend on proprietary functions like json_table.

If you have database access, I think the cleanest way to resolve this is to create a view to hide all the Oracle-specific code from JPA, e.g.:

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;

Then you replace Table2 in your JPA code with View1.

If you can't modify the database, I think you'll have to abandon the Criteria API and use a NativeQuery with bind variable parameters, something like:

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();

As a side note, I recommend never using the case-sensitive Oracle identifiers (with double quotes). Some Oracle tutorials use them, but they only make things more complicated.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.