繁体   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