簡體   English   中英

如何使用JPA Criteria API在字符串的日期字段中搜索

[英]How to search date field for a String using JPA Criteria API

這是我在這里提出的另一個問題的一個問題。 我認為最好在有人( @Franck )指向我指向此鏈接以及這個 鏈接之后再提出一個不同的問題。

我很困惑如何使用JPA Criteria API在數據庫“日期”列(在我的情況下為MySQL DATETIME)中搜索字符串。

這就是我所做的;

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Client> cq = cb.createQuery(Client.class);
Root<Client> entity = cq.from(Client.class);
cq.select(entity);

List<Predicate> predicates = new ArrayList<Predicate>();
predicates.add(cb.like(cb.lower(entity.get("dateJoined").as(String.class)), "%"+search.toLowerCase()+"%")); 

cq.where(predicates.toArray(new Predicate[]{}));
TypedQuery<Client> query = em.createQuery(cq); //<--- Error gets thrown here
return query.getResultList();

但是它失敗,但以下例外;

 java.lang.IllegalArgumentException: Parameter value [%10-2015%] did not match expected type [java.lang.Character] 

其中10-2015是要搜索的字符串;

我堅持如何實現這一目標。 我需要協助。

好的,在嘗試了各種策略之后,這就是我最終完成的工作。

我在這里看到了這篇文章,突然想起了JPA Tuple接口,它是一個可以返回多個結果類型的對象。 因此,執行我的like比較,由於不能簡單地將Date轉換為String,因此下面是步驟:

  1. 我將其列為Tuple
  2. 檢查元組對象是否可以從日期分配
  3. 如果是,則獲取Date-Format表達式並將其傳遞給like表達式。

所以從本質上講,這是我最初擁有的東西,但是顯然失敗了。

predicates.add(cb.like(cb.lower(entity.get("dateJoined").as(String.class)), "%"+search.toLowerCase()+"%")); 

現在,這就是我工作得很好的東西。

Path<Tuple> tuple = entity.<Tuple>get("dateJoined");
if(tuple.getJavaType().isAssignableFrom(Date.class)){
    Expression<String> dateStringExpr = cb.function("DATE_FORMAT", String.class, entity.get("dateJoined"), cb.literal("'%d/%m/%Y %r'"));
    predicates.add(cb.like(cb.lower(dateStringExpr), "%"+search.toLowerCase()+"%"));
}

注意事項 -

  1. 我知道,在任何地方搜索將啟動,我的所有時間都以這種形式提出07/10/2015 10:25:09 PM知道如何格式化用於比較的日期在我,因此我的能力like表達"'%d/%m/%Y %r'"
  2. 這只是適用於Dates的一步。 大多數其他類型,例如int,long,char ...等都可以直接轉換為String,而且隨着我探索更多的數據類型,對於任何其他不能直接轉換為String的Type,我肯定也會做同樣的事情。

盡管這對我來說非常有效,但是在我將其標記為正確答案之前,我將對其進行一些更廣泛的測試,並在此過程中讓任何對我的策略有保留的人都可以公開評論。

最后,向以任何方式提供幫助的那個人加油!

這在我的情況下H2(我將其用於單元測試)中有效,並且我希望在Postgresql和Oracle中也能正常工作,因為TO_CHAR函數似乎受跨數據庫支持。

Path<Date> path = ua.get(MyEntity_.timestamp);
Expression<String> dateStringExpr = cb.function("TO_CHAR", String.class, path, cb.literal("DD.MM.YYYY HH24:MI:SS"));
predicates.add(cb.like(dateStringExpr, "%" + value + "%"));

PS。 MyEntity_代表為實際MyEntity生成的元模型。 您可以在Oracle文檔Criteria API中閱讀有關元模型的信息。

我建議您將搜索字符串轉換為Date對象,然后進行比較

SimpleDateFormat dateFormat = new SimpleDateFormat(...desired date format here...);
Date dateSearchParam = dateFormat.format(search);
predicates.add(cb.eq(entity.get("dateJoined"), dateSearchParam);

或者,如果需要,您可以將Entity中的dateJoined屬性的類型更改為String,而MySQL DB類型仍為DATETIME。 當從數據庫中檢索實體時,可以使用JPA @Convert將DATETIME轉換為java.lang.String(當將實體持久化到DB時,反之亦然)。

在這里查看示例。

屬性轉換器僅在JPA 2.1版本中可用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM