使用CriteriaBuilder.function()

时间:2017-08-17 02:10:28

标签: hibernate jpa

我试图使用JPA做一个简单的选择:

SELECT POW(2, 10) FROM COUNTRY

所以,我试一试:

EntityManager em = getEM();
CriteriaBuilder cb = em.getCriteriaBuilder( );
CriteriaQuery< Object > cq = cb.createQuery( );
cq.from( Country.class );
cq.multiselect( cb.function( "POW", Integer.class, cb.literal( 2 ), cb.literal( 10 ) ) );
em.createQuery( cq ).getResultList( );

这给了我一个QueryException

java.lang.IllegalArgumentException: org.hibernate.QueryException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode
\-[METHOD_CALL] MethodNode: 'function (POW)'
    +-[METHOD_NAME] IdentNode: 'POW' {originalText=POW}
    \-[EXPR_LIST] SqlNode: 'exprList'
        +-[NUM_INT] LiteralNode: '2'
        \-[NUM_INT] LiteralNode: '10'
[select function('POW', 2, 10) from model.Country as generatedAlias0]

然后,我试图施展它:

EntityManager em = getEM();
CriteriaBuilder cb = em.getCriteriaBuilder( );
CriteriaQuery< Object > cq = cb.createQuery( );
cq.from( Country.class );
cq.multiselect( cb.function( "POW", Integer.class, cb.literal( 2 ), cb.literal( 10 ) ).as( Long.class ) );
em.createQuery( cq ).getResultList( );

(我试图将其转换为String和Long。转换为Integer导致与上面相同的异常。)

然后我得到另一个QueryException:

java.lang.IllegalArgumentException: org.hibernate.QueryException: CAST function should only have 2 arguments [select cast(function('POW', 2, 10) as string) from model.Country as generatedAlias0]
[...]
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:655)
... 31 more
Caused by: org.hibernate.QueryException: CAST function should only have 2 arguments
at org.hibernate.hql.internal.ast.SqlGenerator$CastFunctionArguments.betweenFunctionArguments(SqlGenerator.java:300)
at org.hibernate.hql.internal.ast.SqlGenerator.betweenFunctionArguments(SqlGenerator.java:137)
at org.hibernate.hql.internal.antlr.SqlGeneratorBase.methodCall(SqlGeneratorBase.java:2584)
at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectExpr(SqlGeneratorBase.java:2130)
at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectColumn(SqlGeneratorBase.java:1942)
at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectClause(SqlGeneratorBase.java:555)
at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectStatement(SqlGeneratorBase.java:197)
at org.hibernate.hql.internal.antlr.SqlGeneratorBase.statement(SqlGeneratorBase.java:146)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.generate(QueryTranslatorImpl.java:248)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:209)
... 37 more

我做错了什么?

P.S。:我用EclipseLink尝试了上面的查询,它运行正常。

1 个答案:

答案 0 :(得分:0)

正如Hibernate组织成员所述,此问题将在版本6.0 +上解决。

但是他表示可以解决这个问题。如果您遇到此问题,则需要在Dialect级别声明该函数:

// Extends on the best dialect for your case
public class NewDialect extends MySQLDialect {

    public NewDialect( ) {
        registerFunction( "POW", new StandardSQLFunction( "POW", StandardBasicTypes.DOUBLE ) );
    }
}

// In your hibernate config: (assuming you are using StandardServiceRegistryBuilder)
ssrb.applySetting( "hibernate.dialect", "com.example.NewDialect" );

参考:https://hibernate.atlassian.net/browse/HHH-11938