2014-10-09 17 views
12

Tôi có một tình huống trong mệnh đề where tôi có một vị từ và biểu thức duy nhất. Và cả hai cần được ANDed trong mệnh đề where:JPA: Dành riêng và biểu hiện cả trong QueryCriteria trong đó khoản

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

Trong trường hợp này tôi không thể làm điều gì đó như: createQuery.where (predicateNull, regExprLike);

tôi đã cố gắng sử dụng CriteriaBuilder của isTrue() phương pháp:

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

Nhưng nó didnt giúp đỡ.

Tiêu chíTruy vấn hoặc cho phép biến vị ngữ hoặc biểu thức, chứ không phải cả hai, trong mệnh đề where. bất kỳ ý tưởng làm thế nào tôi có thể sử dụng cả hai, các vị từ và biểu thức trong mệnh đề where của QueryCriteria?

Cập nhật ngày 10 tháng 10 năm 2014: Theo đề nghị của Chris, tôi cố gắng sử dụng:

createQuery.where(predicateNull, regExprLike); 

Nhưng truy vấn của tôi không thành công với ngoại lệ:

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] 

mã trông My như:

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

Bạn đã thử thêm vị từ và biểu thức của mình cùng nhau chưa? createQuery.where (criteriaBuilder.and (predicateNull, regExprLike)); – Chris

+0

Có, tôi đã thử. Tôi không nhận được bất kỳ lỗi thời gian biên dịch, nhưng thế hệ truy vấn của tôi không thành công. Tôi đã cập nhật câu hỏi của mình với các bản cập nhật mới nhất. Vui lòng cho tôi biết nếu bạn có thêm thông tin. Cảm ơn. – user613114

+0

@ user613114 bạn đã bao giờ tìm ra điều này chưa? – Crystal

Trả lời

2

Tôi nghĩ vấn đề của bạn là oracle không phân loại 'regexp_like' như một hàm. Để làm cho nó làm việc, bạn cần phải mở rộng Oracle phương ngữ có chức năng đăng ký mới:

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

và sau đó bạn có thể thay đổi bạn mệnh đề where:

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

Tất nhiên, bạn phải đăng ký phương ngữ mới trong persistence.xml

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

Bằng cách nào đó tôi nghĩ rằng cách tiếp cận của bạn đã cho tôi cùng một lỗi gây ra tôi đã thử "createQuery.where (criteriaBuilder.and (predicateNull, regExprLike))". Nhưng tôi nhận ra sai lầm của mình và tôi đã cố gắng chính xác như đề nghị. Và bammm .. Nó làm việc như một sự duyên dáng :) Rất cám ơn vì thời gian và nỗ lực của bạn :) – user613114

Các vấn đề liên quan