Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using JPA 2.0 Criteria API and cast causes generated JPQL to fail in Hibernate

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

like image 723
bruma Avatar asked Nov 24 '10 16:11

bruma


2 Answers

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.

like image 89
Mikko Maunu Avatar answered Jan 02 '23 06:01

Mikko Maunu


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

like image 43
bruma Avatar answered Jan 02 '23 07:01

bruma