1

我需要在 Grails 中使用 GROUP_CONCAT 聚合函数,最好来自 HQL,但也可以使用标准。

我有这个查询:

ClickTracking.executeQuery("SELECT pageId, containerId, GROUP_CONCAT(clicks) as click" +
                                            "FROM  ClickTracking " +
                                            "WHERE pageId =  ? " +
                                            "GROUP BY containerId ", [pageId])

这不起作用,因为 HQL 不知道 GROUP_CONCAT 因为是特定于数据库的。我可以将我的项目与 MySQL 绑定,所以我尝试在 BootStrap.groovy 中添加它:

Configuration conf = grailsApplication.getMainContext().getBean("&sessionFactory").configuration;
conf.addSqlFunction("GROUP_CONCAT", new StandardSQLFunction("GROUP_CONCAT", new StringType()));

没运气。

然后我尝试子类化方言并使用它:

import org.hibernate.dialect.MySQL5InnoDBDialect
import org.hibernate.dialect.function.StandardSQLFunction
import org.hibernate.Hibernate

class ExtendedMySqlDialect extends MySQL5InnoDBDialect {

public ExtendedMySqlDialect() {
    super();
    registerFunction("GROUP_CONCAT", new StandardSQLFunction("GROUP_CONCAT", Hibernate.STRING));

}

}

在 DataSource.groovy

dataSource {
pooled = true
driverClassName = "com.mysql.jdbc.Driver"
dialect = "ExtendedMySqlDialect"
logSql = true

}

仍然没有运气。我得到:

No data type for node: org.hibernate.hql.ast.tree.MethodNode 

-[METHOD_CALL] MethodNode: '(' +-[METHOD_NAME] IdentNode: 'GROUP_CONCAT' {originalText=GROUP_CONCAT} -[EXPR_LIST] SqlNode: 'exprList' -[DOT] DotNode: 'clicktrack0_.clicks' {propertyName=clicks,dereferenceType =ALL,propertyPath=clicks,path={synthetic-alias}.clicks,tableAlias=clicktrack0_,className=com.ui.gorm.ClickTracking,classAlias=null} +-[IDENT] IdentNode: '{synthetic-alias}' { originalText={synthetic-alias}} -[IDENT] IdentNode: 'clicks' {originalText=clicks} . Stacktrace 如下:消息:节点没有数据类型:org.hibernate.hql.ast.tree.MethodNode -[METHOD_CALL] MethodNode : '(' +-[METHOD_NAME] IdentNode: 'GROUP_CONCAT' {originalText=GROUP_CONCAT} -[EXPR_LIST] SqlNode: 'exprList' -[DOT] DotNode: 'clicktrack0_.clicks'{propertyName=clicks,dereferenceType=ALL,propertyPath=clicks,path={synthetic-alias}.clicks,tableAlias=clicktrack0_,className=com.ui.gorm.ClickTracking,classAlias=null} +-[IDENT] IdentNode: '{合成别名}' {originalText={synthetic-alias}} -[IDENT] IdentNode: 'clicks' {originalText=clicks}

Line | Method

->> 156 | org.hibernate.hql.ast.tree.SelectClause 中的 initializeExplicitSelectClause

如果我设置一个断点并查看 grailsApplication.getMainContext().getBean("&sessionFactory").configuration 我可以找到一个名为 sqlFuncions 的属性并且 GROUP_COCNAT 在那里。

我做了一些调试,最后在下面的代码中选择了 SelectExpressionList.java:

public SelectExpression[] collectSelectExpressions() {
    // Get the first child to be considered.  Sub-classes may do this differently in order to skip nodes that
    // are not select expressions (e.g. DISTINCT).
    AST firstChild = getFirstSelectExpression();
    AST parent = this;
    ArrayList list = new ArrayList( parent.getNumberOfChildren() );
    for ( AST n = firstChild; n != null; n = n.getNextSibling() ) {
        if ( n instanceof SelectExpression ) {
            list.add( n );
        }
        else {
            throw new IllegalStateException( "Unexpected AST: " + n.getClass().getName() + " " + new ASTPrinter( SqlTokenTypes.class ).showAsString( n, "" ) );
        }
    }
    return ( SelectExpression[] ) list.toArray( new SelectExpression[list.size()] );
}

似乎 n=n.getNextSibbling() 在某种程度上弄乱了 group_concat,但这很奇怪,因为它来自 antlr 包。

无论如何,我被卡住了,我很好奇如何使用 group_concat (或带有 gorm 的 grails 中的任何其他 db 特定函数)。我正在使用 grails 2.0.4

4

1 回答 1

0

尝试这样的事情:

Yourdomain.withSession{ session ->  
   session.createSQLQuery(yourQueryWithGroup_concat).setLong(yourParameterName,yourParameterValue).list()  
}
于 2013-09-12T13:23:44.157 回答