如何使用JPA2 Criteria API将字符串正确地转换为数字?

时间:2012-02-22 11:48:31

标签: jpa jpa-2.0 criteria-api

我正在尝试使用subselect编写一个查询,其中字符串被强制转换为long。 我可能错过了什么?

查询看起来像:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Task> query = cb.createQuery(Task.class);

Root<Task> from = query.from(Task.class);

Subquery<Long> subquery = query.subquery(Long.class);
Root<EntityKeyword> fromKeyword = subquery.from(EntityKeyword.class); 
subquery.select(fromKeyword.get(EntityKeyword_.relatedToId).as(Long.class));
subquery.where(cb.like(fromKeyword.get(EntityKeyword_.keyword), term));

query.where(cb.in(from.get(ModelEntity_.id)).value(subquery));

其中 EntityKeyword_.relatedToId a是需要强制转换为Long的字符串。

但潜在的Hibernate失败,但有例外:

Last cause: No data type for node: org.hibernate.hql.ast.tree.MethodNode 
 \-[METHOD_CALL] MethodNode: '('
    +-[METHOD_NAME] IdentNode: 'cast' {originalText=cast}
    \-[EXPR_LIST] SqlNode: 'exprList'
       +-[DOT] DotNode: 'entitykeyw1_.keyword' {propertyName=keyword,dereferenceType=ALL,propertyPath=keyword,path=generatedAlias1.keyword,tableAlias=entitykeyw1_,className=l.i.s.m.s.EntityKeyword,classAlias=generatedAlias1}
       |  +-[ALIAS_REF] IdentNode: 'entitykeyw1_.id' {alias=generatedAlias1, className=l.i.s.m.s.EntityKeyword, tableAlias=entitykeyw1_}
       |  \-[IDENT] IdentNode: 'keyword' {originalText=keyword}
       \-[IDENT] IdentNode: 'int8' {originalText=int8}

不知道出了什么问题。任何帮助表示赞赏。

我正在使用Hibernate 3.6.8-Final

3 个答案:

答案 0 :(得分:3)

Criteria API中没有执行从String到Long的转换的方法。

您尝试在 Expression 中使用方法作为进行此转换。 Javadoc解释了为什么最终会出现运行时问题:

  

对表达式执行类型转换,返回一个新表达式   宾语。此方法不会导致类型转换:运行时类型   没有改变。警告:可能导致运行时失败。

CriteriaBuilder确实有bunch of methods用于类型转换,但也不支持字符串到数字的转换。

答案 1 :(得分:2)

以下方法对我有用,可以使用CriteriaBuilder将类型转换为其他数据类型的字符串

CriteriaBuilder queryBuilder = em.getCriteriaBuilder();
Expression roomIdInt = queryBuilder.desc(root.get("room").get("id")).as(Integer.class));
//Expression roomIdInt = queryBuilder.desc(root.get("room").get("id")).as(Long.class));
//Expression roomIdInt = queryBuilder.desc(root.get("room").get("id")).as(Double.class));
//Expression roomIdInt = queryBuilder.desc(root.get("room").get("id")).as(Date.class));
//Expression roomIdInt = queryBuilder.desc(root.get("room").get("id")).as(Boolean.class));

最初,我使用CriteriaBuilder遇到许多错误,并尝试检查数据库日志以检查正在执行的查询。这有助于按要求更正HQL。上述方法在PostgreSQL中工作正常,但解决方案因数据库而异

答案 2 :(得分:0)

类型转换可以由CriteriaBuilder完成。

CriteriaBuilder queryBuilder = em.getCriteriaBuilder(); 
Expression roomIdStr = root.get("room").get("id");
Expression roomIdInt = queryBuilder.function("INT", Integer.class, roomId);

请参阅StackOverflow question 23728108

中的回答