2014-10-09 4 views
12

Ich habe eine Situation, wo ich in meiner Where-Klausel einzigen Prädikat und Ausdruck haben. Und muss sowohl in UNDverknüpft werden, wo Klausel:JPA: Prädikat und Ausdruck sowohl in QueryCriteria where-Klausel

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

In diesem Fall bin ich nicht in der Lage, wie etwas zu tun: createQuery.where (predicateNull, regExprLike);

versuchte ich CriteriaBuilder der isTrue() Methode verwendet:

Predicate predicateNull = criteriaBuilder.isNull(col2); 
Predicate predicateTrue = criteriaBuilder.isTrue(regExprLike); 
createQuery.where(predicateNull, predicateTrue); 

Aber es half nicht.

CriteriaQuery erlaubt Prädikate oder Ausdrücke, aber nicht beide, in where-Klausel. keine Ahnung, wie kann ich beide, Prädikate und Ausdrücke in der Where-Klausel von QueryCriteria verwenden?

-Update 10. Oktober 2014: Wie Chris vorgeschlagen, habe ich versucht, zu verwenden:

createQuery.where(predicateNull, regExprLike); 

Aber meine Abfrage schlägt mit Ausnahme:

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] 

Mein Code sieht wie:

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

Haben Sie versucht, einfach Ihr Prädikat und Ausdruck zusammenzufügen? createQuery.where (criteriaBuilder.and (predicateNull, regExprLike)); – Chris

+0

Ja, ich habe es versucht. Ich bekomme keinen Kompilierzeitfehler, aber meine Abfragegenerierung schlägt fehl. Ich habe meine Frage mit den neuesten Updates aktualisiert. Bitte lassen Sie mich wissen, wenn Sie mehr Informationen haben. Vielen Dank. – user613114

+0

@ user613114 Haben Sie das jemals herausgefunden? – Crystal

Antwort

2

Ich denke, Ihr Problem ist Oracle klassifiziert nicht als eine Funktion 'regexp_like'. Damit es funktioniert, müssen Sie Oracle-Dialekt mit neu registrierten Funktion erweitern:

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)") 
    ); 
} 
} 

und dann können Sie Ihre ändern, wo Klausel:

 createQuery.where(criteriaBuilder.and(predicateNull, criteriaBuilder.equal(regExprLike, 1))); 

Natürlich Ihr haben Ihren neuen Dialekt registrieren in persistence.xml

  <property name="hibernate.dialect" value="path.to.your.dialect.class.Oracle12cExtendedDialect" /> 
+0

Irgendwie dachte ich, Ihr Ansatz gab mir dieselben Fehler, weil ich "createQuery.where (criteriaBuilder.and (predicateNull, regExprLike))" ausprobiert habe. Aber ich habe meinen Fehler erkannt und genau wie vorgeschlagen versucht. Und bammm .. Es funktionierte wie ein Charme :) Vielen Dank für Ihre Zeit und Mühe :) – user613114

Verwandte Themen