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.
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.
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;
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). So to perform my like
comparison, and since Date cannot be simply cast to a String here are the steps;
Tuple
like
expression.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'"
.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.
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_
stands for metamodel generated for real MyEntity
. You may read about Metamodels in Oracle docuemntation for Criteria API.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With