4

I do have a static metamodel with a NUMBER (actually, BigDecimal, don't ask why) column. Now I would like to do a LIKE query against that number column:

CriteriaBuilder cb;
cb.like(entity.get(Entity_.numbercol), "123%");

where entity.get(Entity_.numbercol) returns a Path<BigDecimal>. Naturally, I get a compile error: ...like(Expression<String>, ...) ... not applicable for the arguments (Path<BigDecimal>, ...)

Casting the column with .as(String.class) fails due to some Bug in JPA, but I don't have the bug number at hands right now. It is not fixed in the latest version of JPA/Hibernate, though. Anyway, it results in a runtime exception about some invalid SQL statement being generated.

Now I just need a way to get the criteria API equivalent of the SQL

... WHERE numbercol LIKE '123%';

Searching for the topic already brought up the following responses, which don't help because I have a static metamodel: NHibernate - easiest way to do a LIKE search against an integer column with Criteria API? and JPA/Criteria API - Like & equal problem

Any ideas?

Thanks in advance Dominik

Community
  • 1
  • 1
Dominik Sandjaja
  • 6,326
  • 6
  • 52
  • 77
  • As a workaround and because it is ensured that the wildcard is always the last character of the search string/number, I create a bunch of between expressions, e.g. for `123%` I have `=123 OR between (1230,1239) OR between(12300, 12399) OR between(123000, 123999)` and so on. Not the best way but at least it works. – Dominik Sandjaja Mar 21 '12 at 14:41

2 Answers2

12

For the people, who are still looking for a solution.

Knowing that HQLstr function does the job (at least for Hibernate v. 3.6.9.Final) one can implement his own FunctionExpression like:

//plagiarized from org.hibernate.ejb.criteria.expression.function.CastFunction
public class StrFunction<Y extends Number> extends BasicFunctionExpression<String> implements FunctionExpression<String>, Serializable {
    public static final String FCT_NAME = "str";

    private final Selection<Y> selection;

    public StrFunction(CriteriaBuilder criteriaBuilder, Selection<Y> selection) {
        super((CriteriaBuilderImpl) criteriaBuilder, String.class, FCT_NAME);
        this.selection = selection;
    }

    @Override
    public void registerParameters(ParameterRegistry registry) {
        Helper.possibleParameter(selection, registry);
    }

    @Override
    public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
        return FCT_NAME + '(' + ((Renderable) selection).render(renderingContext) + ')';
    }
}

and then use it:

cb.like(new StrFunction<Long> (cb, root.get(MyObject_.id)), "%mySearchTerm%");
Alexander
  • 381
  • 3
  • 11
0

No, it does not fail because of bug, it works as specified (for example in Javadoc):

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.

Method you use performs cast and you need conversion. In general there is no support to convert from BigDecimal to String in JPA.

Mikko Maunu
  • 41,366
  • 10
  • 132
  • 135
  • Well, I know about that but there is also somewhere a bug which we stepped over. Anyway, thanks for pointing that out here in this context, that should help. – Dominik Sandjaja Mar 22 '12 at 15:05