H2 查询失败,“节点没有数据类型:org.hibernate.hql.internal.ast.tree.MethodNode”

Posted

技术标签:

【中文标题】H2 查询失败,“节点没有数据类型:org.hibernate.hql.internal.ast.tree.MethodNode”【英文标题】:H2 query failing with 'No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode' 【发布时间】:2016-10-27 18:10:37 【问题描述】:

我有一个自定义查询,它适用于 postgres,但在 H2 中失败。

select distinct(to_char(date_requested,'YYYY')) 
from Product 
where date_requested is not null

我得到的例外是:

> Caused by: java.lang.IllegalStateException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode 
     \-[METHOD_CALL] MethodNode: '('
        +-[METHOD_NAME] IdentNode: 'to_char' originalText=to_char
        \-[EXPR_LIST] SqlNode: 'exprList'
           +-[IDENT] IdentNode: 'date_requested' originalText=date_requested
           \-[QUOTED_STRING] LiteralNode: ''YYYY''

我的另一个查询,与 to_char 的用法类似,效果很好:

select count(*), requester 
from Product 
where to_char(date_requested,'YYYY') = '2016' 
group by requester 
ORDER BY Count(*) desc

我确实有最新版本的 H2,1.4.192,所以我知道 to_char 的使用是可以的。

我在这里做错了什么?为什么第一个查询不适用于 H2?

【问题讨论】:

不相关,但是:distinct 不是函数。将表达式放在括号之间不会改变任何不同的东西。 distinct (a)distinct a 相同 是的,我知道这一点。这是我正在为其编写单元测试的同事的查询。无论如何,是的,无关。感谢您的编辑。 在没有混淆层(又名 ORM)的情况下运行查询是否有效 不幸的是,我无法检查这个。我的 DBMS 使用的是不支持 to_char 的旧版 H2 驱动程序。将其更改为使用最新的 H2 驱动程序 jar(取自 link,当我尝试连接时出现错误 java.lang.UnsupportedClassVersionError: org/h2/Driver : Unsupported major.minor version 51.0到 H2 数据库。 【参考方案1】:

我遇到了同样的问题。

通过使用最新版本的 H2,这些 TO_DATE、TRUNC、TO_CHAR 函数在 H2 中呈现。

这里的问题是你使用hibernate作为ORM后端,而普通的H2Dialect不理解这些功能。您可以将此方言子类化以映射新功能。例如,这是我用于 TRUNC 函数的那个​​。

package my.awesome.project;

import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.type.StandardBasicTypes;

public class CustomH2Dialect extends H2Dialect 

    public CustomH2Dialect() 
        super();
        registerFunction("trunc", new StandardSQLFunction("trunc", StandardBasicTypes.TIMESTAMP));
    

然后您将休眠设置“connection.driver_class”替换为:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">

  <persistence-unit name="thePersistenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
        <property name="connection.driver_class" value="org.h2.Driver"/>
        <property name="hibernate.connection.url" value="jdbc:h2:./db/repository"/>
        <property name="hibernate.dialect" value="my.awesome.project.CustomH2Dialect"/>
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        <property name="hibernate.show_sql" value="true" />

    </properties>
  </persistence-unit>

【讨论】:

【参考方案2】:

因此,当我从所有查询中删除 to_char 函数时,问题就消失了。有同事告诉我H2不支持函数的使用。我找不到任何支持相同的文档,但我想我会把它留在这里作为一个选项,以防其他人面临这个问题。

【讨论】:

以上是关于H2 查询失败,“节点没有数据类型:org.hibernate.hql.internal.ast.tree.MethodNode”的主要内容,如果未能解决你的问题,请参考以下文章

Mysql SQL查询DATEDIFF在H2中失败,其中模式是MYSQL

H2:使用嵌套查询的计数查询中的列名重复

插入时间戳时的 H2 org.h2.jdbc.JdbcSQLSyntaxErrorException

使用MYSQL时,Grails条件查询失败,语法错误

H2 - (相当)长插入失败并出现错误 42000

删除约束后 h2 删除列失败