【问题标题】:JPA: How to perform a LIKE with a NUMBER column in a static JPA MetaModel?JPA:如何在静态 JPA 元模型中使用 NUMBER 列执行 LIKE?
【发布时间】:2012-04-05 19:55:50
【问题描述】:

我确实有一个带有 NUMBER(实际上是 BigDecimal,不要问为什么)列的静态元模型。现在我想对该数字列进行 LIKE 查询:

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

其中entity.get(Entity_.numbercol) 返回Path<BigDecimal>。当然,我得到一个编译错误:...like(Expression<String>, ...) ... not applicable for the arguments (Path<BigDecimal>, ...)

由于 JPA 中的一些错误,使用 .as(String.class) 铸造列失败,但我现在手头没有错误编号。不过,它在最新版本的 JPA/Hibernate 中并未修复。无论如何,它会导致生成一些无效 SQL 语句的运行时异常。

现在我只需要一种方法来获取与 SQL 等效的条件 API

... WHERE numbercol LIKE '123%';

搜索该主题时已经出现了以下响应,这无济于事,因为我有一个静态元模型: NHibernate - easiest way to do a LIKE search against an integer column with Criteria API?JPA/Criteria API - Like & equal problem

有什么想法吗?

提前致谢 多米尼克

【问题讨论】:

  • 作为一种解决方法,并且因为确保通配符始终是搜索字符串/数字的最后一个字符,我创建了一堆表达式之间,例如对于123% 我有=123 OR between (1230,1239) OR between(12300, 12399) OR between(123000, 123999) 等等。不是最好的方法,但至少它有效。

标签: hibernate jpa jpa-2.0 criteria-api metamodel


【解决方案1】:

不,它不会因为错误而失败,它按照指定的方式工作(例如在Javadoc 中):

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

您使用的方法执行转换并且您需要转换。 JPA 中一般不支持将 BigDecimal 转换为 String。

【讨论】:

  • 嗯,我知道这一点,但在某个地方我们也发现了一个错误。无论如何,感谢您在这种情况下指出这一点,这应该会有所帮助。
【解决方案2】:

对于仍在寻找解决方案的人们。

知道 HQLstr 函数可以完成这项工作(至少对于 Hibernate v. 3.6.9.Final),一个人可以实现自己的FunctionExpression,例如:

//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) + ')';
    }
}

然后使用它:

cb.like(new StrFunction<Long> (cb, root.get(MyObject_.id)), "%mySearchTerm%");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 2014-12-23
    • 2012-06-06
    • 2014-07-16
    • 2012-12-13
    相关资源
    最近更新 更多