java - example - JPA: Predicado y expresión tanto en QueryCriteria where cláusula
jpa select where (1)
Creo que su problema es que Oracle no clasifica ''regexp_like'' como una función. Para que funcione, debe extender el dialecto de Oracle con la nueva función registrada:
public class Oracle12cExtendedDialect extends Oracle12cDialect {
public Oracle12cExtendedDialect() {
super();
registerFunction(
"regexp_like", new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN,
"(case when (regexp_like(?1, ?2)) then 1 else 0 end)")
);
}
}
y luego puedes cambiar tu cláusula where:
createQuery.where(criteriaBuilder.and(predicateNull, criteriaBuilder.equal(regExprLike, 1)));
Por supuesto, debes registrar tu nuevo dialecto en persistence.xml
<property name="hibernate.dialect" value="path.to.your.dialect.class.Oracle12cExtendedDialect" />
Tengo una situación en la que en mi cláusula where tengo un solo predicado y expresión. Y ambos deben estar en AND en la cláusula where:
Expression<String> col1 = tableEntity.get("col1");
Expression<String> regExpr = criteriaBuilder.literal("//.//d+$");
Expression<Boolean> regExprLike = criteriaBuilder.function("regexp_like", Boolean.class, col, regExpr);
Expression<TableEntity> col2= tableEntity.get("col2");
Predicate predicateNull = criteriaBuilder.isNull(col2);
createQuery.where(cb.and(predicateNull));
createQuery.where(regExprLike);
En este caso, no puedo hacer algo como: createQuery.where (predicateNull, regExprLike);
Intenté usar el método isTrue () de CriteriaBuilder:
Predicate predicateNull = criteriaBuilder.isNull(col2);
Predicate predicateTrue = criteriaBuilder.isTrue(regExprLike);
createQuery.where(predicateNull, predicateTrue);
Pero no ayudó.
CriteriaQuery permite predicados o expresiones, pero no ambos, en cláusula where. ¿Alguna idea de cómo puedo usar predicados y expresiones en la cláusula QueryCriteria''s where?
Actualización 10 de octubre de 2014: Como sugirió Chris, traté de usar:
createQuery.where(predicateNull, regExprLike);
Pero mi consulta falla con excepción:
Caused by: org.jboss.arquillian.test.spi.ArquillianProxyException: org.hibernate.hql.internal.ast.QuerySyntaxException : unexpected AST node: ( near line 1, column 311 [select coalesce(substring(generatedAlias0.col1,0,(locate(regexp_substr(generatedAlias0.col1, :param0),
generatedAlias0.col1)-1)), generatedAlias0.col1), generatedAlias0.col1
from com.temp.TableEntity as generatedAlias0
where (generatedAlias0.col2 is null ) and ( regexp_like(generatedAlias0.col1, :param1))] [Proxied because : Original exception not deserilizable, ClassNotFoundException]
Mi código se ve así:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]> createQuery = criteriaBuilder.createQuery(Object[].class);
Root<TableEntity> tableEntity = createQuery.from(TableEntity.class);
Expression<String> path = tableEntity.get("col1");
Expression<String> regExpr = criteriaBuilder.literal("//.//d+$");
Expression<String> regExprSubStr = criteriaBuilder.function("regexp_substr", String.class, path, regExpr);
Expression<Boolean> regExprLike = criteriaBuilder.function("regexp_like", Boolean.class, path, regExpr);
Expression<Integer> l3 = criteriaBuilder.locate(path, regExprSubStr);
Expression<Integer> minusOne = criteriaBuilder.literal(1);
Expression<Integer> l3Sub1 = criteriaBuilder.diff(l3, minusOne);
Expression<Integer> zeroIndex = criteriaBuilder.literal(0);
Expression<String> s3 = criteriaBuilder.substring(path, zeroIndex, l3Sub1);
Expression<TableEntity> col1 = tableEntity.get("col1");
Expression<TableEntity> col2 = tableEntity.get("col2");
Expression<String> coalesceExpr = criteriaBuilder.coalesce(s3, path);
createQuery.multiselect(coalesceExpr, col1);
Predicate predicateNull = criteriaBuilder.isNull(col2);
createQuery.where(criteriaBuilder.and(predicateNull, regExprLike));
String query = entityManager.createQuery(createQuery).unwrap(org.hibernate.Query.class).getQueryString();