这是一个转移我的另一个问题here的问题。在某人(@Franck)将我指向this link和this one too后,我认为最好将其作为一个不同的问题。
我对如何使用JPA Criteria API在数据库Date列(在我的案例中是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
是要搜索的字符串;
我坚持如何实现这一目标。我需要一些帮助。
答案 0 :(得分:4)
好的,经过大量的各种策略试验,这就是我最终的工作。
我看到了这篇文章here,突然想起了JPA Tuple
接口,它是一个可以返回多个结果类型的对象。所以要执行我的like
比较,并且因为Date不能简单地转换为字符串,这里是步骤;
Tuple
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()+"%"));
}
注意 - 值得考虑的事项 -
07/10/2015 10:25:09 PM
格式显示,因此我能够知道如何格式化我的like
表达式中的比较日期"'%d/%m/%Y %r'"
。虽然这对我来说非常合适,但在我将其标记为正确答案之前,我会对其进行更广泛的测试,并在此过程中保持开放以供任何有任何保留意见的人发表评论。我的策略。
最后,对于那个以任何方式帮助过的人......干杯!
答案 1 :(得分:1)
这适用于我的情况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 docuemntation中阅读有关Criteria API的元模型。
答案 2 :(得分:0)
我建议你将搜索字符串转换为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。当从DB中检索实体时,您可以利用JPA @Convert将DATETIME转换为java.lang.String(反之亦然,当实体被持久化到DB时)。
查看示例here。
属性转换器仅适用于JPA 2.1版本。