【问题标题】:Hibernate assumes arguments in HQL query where there are noneHibernate 假定 HQL 查询中没有参数
【发布时间】:2011-09-16 04:21:24
【问题描述】:

为什么 Hibernate 抱怨以下查询:

  public Set<Long> findImageVariantIdsWithOutOfBoundsDimension() {
    final StringBuilder queryBuilder = new StringBuilder();
    queryBuilder.append("select id from ImageVariant where ");
    // imageVariantType is something like R_110X75 with 110 being max x.
    // cast(substring( extracts 110.
    queryBuilder.append("dimensionX > cast(substring(imageVariantType, 3, locate('X', imageVariantType) - 3), int) ");
    queryBuilder.append("or ");
    // imageVariantType is something like R_110X75 with 75 being max y.
    // cast(substring( extracts 75.
    queryBuilder.append("dimensionY > cast(substring(imageVariantType, locate('X', imageVariantType) + 1), int)");
    final Query query = getEntityManager().createQuery(queryBuilder.toString());
    @SuppressWarnings("unchecked")
    final Set<Long> result = new HashSet<Long>(query.getResultList());
    return result;
  }

警告是Function template anticipated 3 arguments, but 2 arguments encountered。但是,我的查询既不包含标记也不包含参数。由于cast 是一个特定于 Hibernate 的函数(JPQL 中没有字符串到整数的转换),我认为这是一个 HQL 问题。

当我调试 Hibernate 的 TemplateRenderer 时,我看到它的内部参数列表是 ['X', imagevaria0_.imagevarianttype]

【问题讨论】:

标签: hibernate hql


【解决方案1】:

当您知道它是特定于休眠的功能时,为什么要使用 JPA 创建查询?

尝试获取休眠会话并在其上创建查询。您可以使用

获得休眠会话
Session session = (Session) em.getDelegate();

编辑:getEntityManager().createQuery(queryBuilder.toString()); 假设您传递的查询字符串是 JPQL 对吗?您不应该在此使用 HQL 特定功能。 您需要获取 HQL 会话而不是 JPA 实体管理器来创建查询。

编辑:我试过了,对我来说效果很好。我的配置是带有 Hibernate 3.6.0 和 MySQL 5.1.28 的 JPA 2.0。你的配置是什么? ——

【讨论】:

  • 对不起,我不太明白你的回答。是否建议使用查询 API?
  • 不,您可以将 HQL 字符串传递给 createQuery() 方法,因为您获得的 EM 实例是 Hibernate 实体管理器。从 Hibernate 3 开始,JPQL 是 HQL 的子集。
  • 我怀疑这违反了多态性原则。这就像指向 ArrayList 对象的 List 引用不应该能够调用任何 ArrayList 特定函数。我没有随时设置 JPA 项目来确认这一点。但是您是否尝试过显式地获取休眠会话?
  • 我错了。我试过这个,它对我来说很好。我的配置是带有 Hibernate 3.6.0 和 MySQL 5.1.28 的 JPA 2.0。你的配置是什么?
【解决方案2】:

这基本上是 Hibernate 警告,即某些 SQL 函数未使用其所有可接受的参数调用。在您的情况下,这是 LOCATE 函数。此函数的语法为LOCATE(string1, string 2, [start]),其中start 是一个可选参数,用于指定从何处开始搜索的第一个字符的索引。

在您的情况下,您将此函数调用为locate('X', imageVariantType),只传递两个参数而不是允许的最大值 3。 Hibernate 类TemplateRenderer 检测到这一点并生成您看到的警告消息。

我已经向 Hibernate 团队提出了bug 以降低此消息的严重性(因为它不会阻止查询在大多数情况下正常工作)或实施更好的检查以使警告不会在对给定 SQL 函数有效的情况下生成。

对于遇到类似问题的任何人,如果查询正常,则可以简单地忽略此警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多