JPA 条件 API 和 Oracle JSON_TABLE 函数
JPA Criteria API and Oracle JSON_TABLE function
我在基于sql代码的java中编写条件时遇到问题,我们必须使用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();
这很难,因为您将螺丝刀用作锤子。标准 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。
如果您不能修改数据库,我认为您将不得不放弃标准 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 教程使用它们,但它们只会使事情变得更复杂。
我在基于sql代码的java中编写条件时遇到问题,我们必须使用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();
这很难,因为您将螺丝刀用作锤子。标准 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。
如果您不能修改数据库,我认为您将不得不放弃标准 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 教程使用它们,但它们只会使事情变得更复杂。