2017-06-29 97 views
1

我最近試圖修改我的Hibernate的Session API來JPA API和我跑了一些問題Hibernate的JPA QueryBuilder.like

這裏是我的老會話代碼

Criteria criteria = session().createCriteria(Book.class);  

    // SEARCH both name, ispn field in the db 
    if(search != null && !search.isEmpty()){ 
     Criterion name = Restrictions.ilike("name", search, MatchMode.ANYWHERE); // This use to return a list of similar results.. 
     Criterion ispn = Restrictions.ilike("ispn", search, MatchMode.ANYWHERE); 

     LogicalExpression orExp = Restrictions.or(name, ispn); 

     criteria.add(orExp); 
    } 

這是我實現的嘗試CriteriaBuilder

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 

    CriteriaQuery<Book> criteria = builder.createQuery(Book.class); 

    Root<Book> root = criteria.from(Book.class); 

    criteria.select(root); 



    if(search != null && !search.isEmpty()){ 

     System.out.println(search); 

     Predicate predicateName = builder.like(root.get(Book_.name), search); // root.get(Book_.name) must match exactly `search` for it to return anything. 

     // Predicate predicateIspn = builder.like(root.get(Book_.ispn), search); 

     criteria.where(predicateName); 
    } 

    List<Book> books = entityManager.createQuery(criteria).getResultList(); 

    return books; 

問題

  1. Predicate predicateName = builder.like(root.get(Book_.name), search); CirteriaBuilder.like似乎並沒有工作我必須確保search完美匹配root.get(Book_.name)爲它返回結果。

我已經看過休眠文件好像CriteriaBuilder.like只需要2個參數是一個從數據庫映射root.get(Book_.name)比較輸入search沒有選擇,我可以告訴它MatchMode.ANYWHERE拍攝。有什麼建議麼?或者我可能使用錯誤的方法?

  1. LogicalExpression orExp = Restrictions.or(name, ispn);它用於檢查輸入是否匹配nameispn。但是使用JPA CriteriaBuilder,我會如何做到這一點?我環顧四周,一些教程就是找不到,有一個完整的CRUD實例教程...

謝謝

回答

1
  1. 包裹搜索到「%」 +「%」 - >建設者.like(root.get(Book_.ispn),'%'+ search +'%')。

更好地創建util方法並重用它。像:

public staic String wrapToLike(String value) { 

     return value == null ? "%" : "%"+value"%"; 
    } 

或:

//root.get(Book_.name) - path 
public Predicate createLikePredicate(CriteriaBuilder builder , Path path , String search) 
    return builder.like(path, wrapToLike(search)) 
} 

2.

Predicate predicateName = builder.like(root.get(Book_.name), wrapToLike(search)); 
Predicate predicateIspn = builder.like(root.get(Book_.ispn), wrapToLike(search)); 

Restrictions.or(predicateName ,predicateIspn); 

它應該是這樣的:

public List<Book> findBooksBySearchKey(String search) { 
    CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
    CriteriaQuery<Book> criteria = builder.createQuery(Book.class); 
    Root<Book> root = criteria.from(Book.class); 
    criteria.select(root); 
    applySearchPredicate(builder, criteria, root, search); 
    return entityManager.createQuery(criteria).getResultList(); 
} 

private void applySearchPredicate(CriteriaBuilder builder, CriteriaQuery<Book> criteria, Root<Book> root, String search) { 
    if (search != null && search.trim().length() > 0) { 
     Predicate predicateName = builder.like(root.get(Book_.name), wrapToLike(search)); 
     Predicate predicateIspn = builder.like(root.get(Book_.ispn), wrapToLike(search)); 
     criteria.where(builder.or(predicateName , predicateIspn)); 
    } 
} 

public static String wrapToLike(String value) { 
    return value == null ? "%" : "%"+value+"%"; 
} 
+0

謝謝你這麼多的額外的建議! –

0

MatchMode是一個最好的util這有助於消除你的Hibernate代碼直接使用的 '%'。但是沒有意識到JPA中有這樣的實用程序。

使用的最佳實踐,用於包裝搜索到 '%' +'%,我們可以重用MatchMode的代碼枚舉本身有一個解決辦法:

public staic String wrapToLike(String value) { 
    return value == null ? "%" : MatchMode.ANYWHERE.toMatchString(value); 
} 

MatchMode.ANYWHERE.toMatchString(STR) :toMatchString方法將 值字符串轉換爲從中調用它的枚舉。

選項:

  • ANYWHERE: '%' +值+ '%'
  • END: '%' +值
  • START:值+ '%'
  • EXACT:值