2010-12-08 12 views
3

私は、最高と最低のスコアを見つけるために、SELECTHibernate/HQL/JPQL:CASE WHEN ... THEN NULL ELSE ... END(ClassCastException)の何が問題なのですか?

... 
MAX(CASE WHEN scf.finalScore = 20 OR scf.finalScore = 0 THEN NULL ELSE scf.finalScore END) AS hi, 
MIN(CASE WHEN scf.finalScore = 20 OR scf.finalScore = 0 THEN NULL ELSE scf.finalScore END) AS lo, 
... 

に、次のJPQL/HQLスニペットを持っています。 (scf)またはスコアのスコアが20または0の場合は、MINとMAXで無視される特別な結果を持つゲームです。

Exception in thread "main" java.lang.ClassCastException: org.hibernate.hql.ast.tree.SqlNode cannot be cast to org.hibernate.hql.ast.tree.SelectExpression 
    at org.hibernate.hql.ast.tree.CaseNode.getFirstThenNode(CaseNode.java:44) 
    at org.hibernate.hql.ast.tree.CaseNode.getDataType(CaseNode.java:40) 
    at org.hibernate.hql.ast.util.SessionFactoryHelper.findFunctionReturnType(SessionFactoryHelper.java:402) 
    at org.hibernate.hql.ast.tree.AggregateNode.getDataType(AggregateNode.java:82) 
    at org.hibernate.hql.ast.tree.ConstructorNode.resolveConstructorArgumentTypes(ConstructorNode.java:163) 
    at org.hibernate.hql.ast.tree.ConstructorNode.prepare(ConstructorNode.java:141) 
    at org.hibernate.hql.ast.HqlSqlWalker.processConstructor(HqlSqlWalker.java:996) 
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectExpr(HqlSqlBaseWalker.java:2260) 
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectExprList(HqlSqlBaseWalker.java:2121) 
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectClause(HqlSqlBaseWalker.java:1522) 
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:593) 
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301) 
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:244) 
    at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:254) 
    at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:185) 
    at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136) 
    at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:101) 
    at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:80) 
    at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:124) 
    at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156) 
    at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135) 
    at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1770) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:272) 
    at tld.standalone.Main.executeJpqlStatement(Main.java:70) 
    at tld.standalone.Main.main(Main.java:58) 

何が問題になっています:

Hibernateは例外がスローされますか?それは私のコードですか?休止状態のバグ?

問題は、HibernateがTHEN内部でNULLを処理できないようです: "集計関数を使用しない場合の" scf.finalScore IN(0、20)THEN NULL ELSE scf.finalScore END AS playsscore "同じ例外。だから、これはHibernateのバグですか?

答えて

1

JPQLでは、集約関数ではCASEを許可していませんが、Hibernateはその文法で制限しないため、AST処理中に例外がスローされます。 JPA仕様から

:だから

aggregate_expression ::= 
    { AVG | MAX | MIN | SUM } ([DISTINCT] state_field_path_expression) | 
    COUNT ([DISTINCT] identification_variable | state_field_path_expression | 
     single_valued_object_path_expression) 

state_field_path_expression ::= 
    general_identification_variable.{single_valued_object_field.}*state_field 

、あなたはこの種のロジック用のネイティブSQLクエリを必要とします。

+1

私はブール論理を逆にして、ELSEにNULLを入れて、それを動作させました:MAX(ケース)scf.finalScore NOT IN(0,20)THEN scf.finalScore ELSE NULL END)AS hi。 – Kawu

+0

CASEと集約関数についてのあなたの発言は正しいが、HibernateがTHENのNULLに問題がある理由については答えていない:a "CASE WHEN scf.finalScore IN(0,20)THEN NULL ELSE scf.finalScore END AS playedscore集計機能を持たない場合でも同じ例外がスローされます。これはHibernateのバグですか? – Kawu