我搜索过类似的问题,发现对我这个特别奇怪的问题没有任何帮助。异常消息似乎是可以理解的,但是明智的参考它的原因以及在哪里进行适当的更正仍然胜过我...我喜欢 为什么是期望的类型java.lang .Character ???
我有HashMap<String, Object>
名为params
,其中包含我需要用来将查询结果过滤到MySQL数据库的所有搜索参数,所以这里是我如何构建查询使用JPA Criteria API。
目的是在所有指定的dbColumns
中搜索作为名为search
的参数传递的字符串
List<String> dbColumns = Arrays.asList("firstname", "lastname", "username", "email", "mobilenumber", "dateJoined");
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>();
if(params.containsKey("search") && StringUtils.isNotBlank(search)){
String search = String.valueOf(params.get("search"));
for(String column : dbColumns){
predicates.add(cb.like(cb.lower(entity.get(column).as(String.class)), "%"+search.toLowerCase()+"%"));
}
}
cq.where(predicates.toArray(new Predicate[]{}));
TypedQuery<Client> query = em.createQuery(cq); //<--- Error gets thrown here
return query.getResultList();
但是我一直收到这个错误。 参数值[%tunji%]与此行TypedQuery<Client> query = em.createQuery(cq);
请参阅下面的StackTrace片段;
Caused by: java.lang.IllegalArgumentException: Parameter value [%tunji%] did not match expected type [java.lang.Character]
at org.hibernate.ejb.AbstractQueryImpl.validateParameterBinding(AbstractQueryImpl.java:370) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.AbstractQueryImpl.registerParameterBinding(AbstractQueryImpl.java:343) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:370) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.criteria.CriteriaQueryCompiler$1$1.bind(CriteriaQueryCompiler.java:194) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.criteria.CriteriaQueryCompiler.compile(CriteriaQueryCompiler.java:247) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:622) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.jboss.as.jpa.container.AbstractEntityManager.createQuery(AbstractEntityManager.java:96) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
这实际上让我很困惑,因为我在任何时候都没有提到java.lang.Character
。此外,除dateJoined
之外的所有MySQL列都是VARCHAR类型,它应映射到java的 String
类型。
dbColumn dateJoined
属于MySQL类型DATETIME,因此我使用entity.get(column).as(String.class)
,以便将日期的String表示与search
字符串进行比较。
所以我想知道这个错误可能是什么原因以及如何最好地解决这个问题。任何帮助都将受到高度赞赏。
修改
回复@Ish ...这里是Client
实体的样子
@Entity
@Table(name="client")
@NamedQueries({
@NamedQuery(name="Client.findAll", query="SELECT c FROM Client c")
})
public class Client implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(unique=true, nullable=false)
private int id;
@Column(length=255)
private String email;
@Column(length=50)
private String firstname;
@Column(length=50)
private String lastname;
@Column(length=20)
private String mobilenumber;
@Column(unique=true, length=255)
private String username;
@Column(nullable=false, name="datejoined")
private Date dateJoined;
//... getters ... and ... setters
}
答案 0 :(得分:1)
日期无法强制转换为字符串。见this。您对Expression.as()方法的理解不是现实中发生的事情。
答案 1 :(得分:0)
在对各种策略进行了一些很好的实验之后,这就是我最终的工作。
感谢帖子here的引导,让我记住了JPA Tuple
接口,它本质上是一个可以返回多个结果类型的对象。所以要执行我的like
比较,并且因为Date不能简单地转换为字符串,这里是步骤;
Tuple
like
表达式。现在,这就是我用以前的代码替换并且工作得非常漂亮;
List<String> dbColumns = Arrays.asList("firstname", "lastname", "username", "email", "mobilenumber", "dateJoined");
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>();
if(params.containsKey("search") && StringUtils.isNotBlank(search)){
String search = String.valueOf(params.get("search"));
List<Predicate> ORPredicates = new ArrayList<Predicate>();
for(String column : dbColumns){
Path<Tuple> tuple = entity.<Tuple>get(column);
if(tuple.getJavaType().isAssignableFrom(Date.class)){
Expression<String> dateStringExpr = cb.function("DATE_FORMAT", String.class, entity.get(column), cb.literal("'%d/%m/%Y %r'"));
ORPredicates.add(cb.like(cb.lower(dateStringExpr), "%"+search.toLowerCase()+"%"));
}else{
ORPredicates.add(cb.like(cb.lower(entity.get(column).as(String.class)), "%"+search.toLowerCase()+"%"));
}
}
predicates.add(cb.or(ORPredicates.toArray(new Predicate[]{})));
}
cq.where(predicates.toArray(new Predicate[]{}));
TypedQuery<Client> query = em.createQuery(cq); //<--- Error gets thrown here
return query.getResultList();
注意 - 值得考虑的事项 -
07/10/2015 10:25:09 PM
格式显示,因此我能够知道如何格式化我的like
表达式中的比较日期"'%d/%m/%Y %r'"
。虽然这对我来说非常合适,但我仍然可以对任何对我的策略有任何保留意见的人保持开放态度,我只会将其标记为正确的答案。测试
如果这有助于你以任何方式...干杯交配!