使用 JPA 2.0 Criteria API 和强制转换会导致生成的 JPQL 在 Hibernate 中失败

发布于 2024-10-04 14:21:56 字数 1657 浏览 5 评论 0原文

我是新 JPA 2.0 Criteria API 的首次用户,当我需要将数字字段转换为字符串以将其与字符串参数进行比较时,我遇到了问题。原因是我想搜索部分数字,因此我在 CriteriaBuilder 上使用“like”。下面是一个代码示例:

CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<ParcelDO> cq = cb.createQuery(ParcelDO.class);
        Root<ParcelDO> parcelDO = cq.from(ParcelDO.class);
        cq.select(parcelDO);

        String parcelNumberId = parcelSearchDetailDO.getParcelNumberId();
        if (parcelNumberId != null && !parcelNumberId.isEmpty()) {
            Predicate parcelNumberIdPredicate = cb.like(
                    parcelDO.<Long> get("parcelNumberId").as(String.class),
                    parcelNumberId + "%");

            if (cq.getRestriction() != null) {
                cq.where(cq.getRestriction(), parcelNumberIdPredicate);
            } else {
                cq.where(parcelNumberIdPredicate);
            }
        }

重要的部分是

Predicate parcelNumberIdPredicate = cb.like(
                    parcelDO.<Long> get("parcelNumberId").as(String.class),
                    parcelNumberId + "%");

我使用 Criteria API 将 Path 转换为 CriteriaBuilder 上类似方法所需的表达式。

现在,当我运行并执行此代码时,底层 JPA 2.0 实现 Hibernate 会失败,并出现以下异常:

Caused by: org.hibernate.hql.ast.QuerySyntaxException:
expecting CLOSE, found '(' near line 1, column 117 
[select generatedAlias0 from domain.ParcelDO as generatedAlias0 where
cast(generatedAlias0.parcelNumberId as varchar2(255 char)) like :param0]

在我看来,Hibernate 正在生成不正确的 JPQL。

我不知道出了什么问题,你能帮忙吗?

我使用最新的Hibernate版本(3.6.0.CR2)

谢谢

I am a first time user of the new JPA 2.0 Criteria API and I 'm running into a problem when I need to cast a number field to String to compare it with a String parameter. Reason is that I want to search for partial numbers, so I use a 'like' on the CriteriaBuilder. Here's a code sample:

CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<ParcelDO> cq = cb.createQuery(ParcelDO.class);
        Root<ParcelDO> parcelDO = cq.from(ParcelDO.class);
        cq.select(parcelDO);

        String parcelNumberId = parcelSearchDetailDO.getParcelNumberId();
        if (parcelNumberId != null && !parcelNumberId.isEmpty()) {
            Predicate parcelNumberIdPredicate = cb.like(
                    parcelDO.<Long> get("parcelNumberId").as(String.class),
                    parcelNumberId + "%");

            if (cq.getRestriction() != null) {
                cq.where(cq.getRestriction(), parcelNumberIdPredicate);
            } else {
                cq.where(parcelNumberIdPredicate);
            }
        }

The important part is

Predicate parcelNumberIdPredicate = cb.like(
                    parcelDO.<Long> get("parcelNumberId").as(String.class),
                    parcelNumberId + "%");

where I use the Criteria API to convert the Path into a Expression needed for the like method on the CriteriaBuilder.

Now when I run and it executes this code, the underlying JPA 2.0 implementation Hibernate fails with the following exception:

Caused by: org.hibernate.hql.ast.QuerySyntaxException:
expecting CLOSE, found '(' near line 1, column 117 
[select generatedAlias0 from domain.ParcelDO as generatedAlias0 where
cast(generatedAlias0.parcelNumberId as varchar2(255 char)) like :param0]

Looks to me like Hibernate is generating a JPQL that is not correct.

I have no idea what is wrong, can you help?

I use the latest Hibernate version (3.6.0.CR2)

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

人间☆小暴躁 2024-10-11 14:21:56

对于 JPA 来说,Expression.as 方法被用于达到错误的目的。将 Expression 转换为 Expression 不应该通过 Expression.as。当然,如果有清晰的错误消息而不是不正确的 JPQL,那就太好了。

正如文档中所述,它执行类型转换,这与从类型到其他类型的转换是不同的概念:

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

What it comes to JPA, Expression.as method is used to serve wrong purpose in question. Casting Expression<Number> to Expression<String> is not supposed to work via Expression.as. Of course it would be nice to have clear error message instead of incorrect JPQL.

As said in documentation, it performs typecast, which is different concept than conversion from type to other:

Perform a typecast upon the expression, returning a new expression
object. This method does not cause type conversion: the runtime type
is not changed. Warning: may result in a runtime failure.

゛清羽墨安 2024-10-11 14:21:56

正如 axtavt 在问题的评论中所述,这是 Hibernate 3.6 http: //opensource.atlassian.com/projects/hibernate/browse/HHH-5755

As axtavt stated in the comments in the question, it is a bug in Hibernate 3.6 http://opensource.atlassian.com/projects/hibernate/browse/HHH-5755

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文