[英]How to search date field for a String using JPA Criteria API
This is a question that spins off my other Question here . 这是我在这里提出的另一个问题的一个问题。 I thought it would be best put as a different question after someone( @Franck ) pointed me to this link and this one too . 我认为最好在有人( @Franck )指向我指向此链接以及这个 链接之后再提出一个不同的问题。
I'm stumped on how to search for a string in a database Date column (in my case MySQL DATETIME) using the JPA Criteria API. 我很困惑如何使用JPA Criteria API在数据库“日期”列(在我的情况下为MySQL DATETIME)中搜索字符串。
Here's what I've done; 这就是我所做的;
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();
But it fails with the following exception; 但是它失败,但以下例外;
java.lang.IllegalArgumentException: Parameter value [%10-2015%] did not match expected type [java.lang.Character]
where
10-2015
is the String being searched for; 其中10-2015
是要搜索的字符串;
I'm stuck on how to go by achieving this. 我坚持如何实现这一目标。 I need some help. 我需要协助。
Ok, after lots of experimenting with various strategies, here's what I did that finally worked. 好的,在尝试了各种策略之后,这就是我最终完成的工作。
I saw this post here and suddenly remembered the JPA Tuple
Interface which is an Object that can return multiple result Type(s). 我在这里看到了这篇文章,突然想起了JPA Tuple
接口,它是一个可以返回多个结果类型的对象。 So to perform my like
comparison, and since Date cannot be simply cast to a String here are the steps; 因此,执行我的like
比较,由于不能简单地将Date转换为String,因此下面是步骤:
Tuple
我将其列为Tuple
like
expression. 如果是,则获取Date-Format表达式并将其传递给like
表达式。 So essentially, here's what I initially had which was apparently failing; 所以从本质上讲,这是我最初拥有的东西,但是显然失败了。
predicates.add(cb.like(cb.lower(entity.get("dateJoined").as(String.class)), "%"+search.toLowerCase()+"%"));
Now, this is what I have that works beautifully; 现在,这就是我工作得很好的东西。
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()+"%"));
}
NOTE-WORTHY CONSIDERATIONS - 注意事项 -
07/10/2015 10:25:09 PM
hence my ability to know how to format the Date for the comparison in my like
expression as "'%d/%m/%Y %r'"
. 我知道,在任何地方搜索将启动,我的所有时间都以这种形式提出07/10/2015 10:25:09 PM
知道如何格式化用于比较的日期在我,因此我的能力like
表达"'%d/%m/%Y %r'"
。 Though this works perfectly for me, but before I mark this as the right answer, I'm going to subject it to some more extensive tests and in the process keep it open for comments by anyone that has any reservations about my strategy. 尽管这对我来说非常有效,但是在我将其标记为正确答案之前,我将对其进行一些更广泛的测试,并在此过程中让任何对我的策略有保留的人都可以公开评论。
And finally, to that one person that this helped out in any way... Cheers! 最后,向以任何方式提供帮助的那个人加油!
This works in my case H2 (I use it for unit-tests), and I hope will work as well in Postgresql and Oracle, since TO_CHAR function seems to be cross-DB supported. 这在我的情况下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. PS。 MyEntity_
stands for metamodel generated for real MyEntity
. MyEntity_
代表为实际MyEntity
生成的元模型。 You may read about Metamodels in Oracle docuemntation for Criteria API . 您可以在Oracle文档Criteria API中阅读有关元模型的信息。
I would suggest you convert you search string to Date object, and do the comparison 我建议您将搜索字符串转换为Date对象,然后进行比较
SimpleDateFormat dateFormat = new SimpleDateFormat(...desired date format here...);
Date dateSearchParam = dateFormat.format(search);
predicates.add(cb.eq(entity.get("dateJoined"), dateSearchParam);
Or if you want, you can change the type of your dateJoined attribute in your Entity to String, while your MySQL DB type remains DATETIME. 或者,如果需要,您可以将Entity中的dateJoined属性的类型更改为String,而MySQL DB类型仍为DATETIME。 You can utilize JPA @Convert to convert DATETIME to java.lang.String when Entity is retrieved from DB (and vice-versa when Entity is being persisted to DB). 当从数据库中检索实体时,可以使用JPA @Convert将DATETIME转换为java.lang.String(当将实体持久化到DB时,反之亦然)。
Attribute Converters are only available in JPA 2.1 version. 属性转换器仅在JPA 2.1版本中可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.