All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gorm.tools.mango.jpql.PagedQuery.groovy Maven / Gradle / Ivy

There is a newer version: 7.3.74
Show newest version
/*
* Copyright 2022 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License")
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
package gorm.tools.mango.jpql

import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic

import org.grails.datastore.gorm.GormStaticApi
import org.grails.orm.hibernate.GrailsHibernateTemplate
import org.grails.orm.hibernate.HibernateGormStaticApi
import org.grails.orm.hibernate.query.HibernateHqlQuery
import org.hibernate.ScrollableResults
import org.hibernate.Session
import org.hibernate.query.Query

import gorm.tools.mango.hibernate.PathKeyMapPagedList
import gorm.tools.mango.hibernate.PathKeyMapResultTransformer

/**
 * Helper to get the hibernate template and query so we can do scrollable to add totalCount logic with JPAQL.
 * Primarily for our projection and aggregate queries, especially with having clauses, are not easy to simply add count substition.
 *
 * TODO If performance will be an issue with Scrollable then alternaitive is to wrap the query as and do a select count(*) on it
 * But that will be tricky with HQL.
 */
@CompileStatic
class PagedQuery {
    // org.hibernate.query.Query query
    HibernateGormStaticApi staticApi
    GrailsHibernateTemplate hibernateTemplate

    /**
     * The aliases we created.
     * for example a projection:['amount':'sum'] will get an alias of 'amount_sum',
     * we remove that _sum suffix automatically because its set in the systemAliases.
     * but if we did projection:['amount as amount_totals':'sum'] then that is user specified. we dont want to remove the _totals suffix.
     */
    List systemAliases = [] as List

    PagedQuery(GormStaticApi staticApi) {
        this.staticApi = (HibernateGormStaticApi)staticApi;
        hibernateTemplate = this.staticApi.getHibernateTemplate()
    }

    PagedQuery(GormStaticApi staticApi, List systemAliases) {
        this(staticApi)
        this.systemAliases = systemAliases
    }


    Integer countQuery(CharSequence queryString, Map params){

        def template = hibernateTemplate
        params = new HashMap(params)

        if(queryString instanceof GString) {
            queryString = buildNamedParameterQueryFromGString((GString) queryString, params)
        }

        return (Integer) template.execute { Session session ->
            Query q = (Query) session.createQuery(queryString.toString())
            populateQueryWithNamedArguments(q, params)
            q.setReadOnly(true)
            // MIN_VALUE gives hint to JDBC driver to stream results
            q.setFetchSize(50) // double normal paging size
            ScrollableResults results = q.scroll()
            results.last()
            int total = results.getRowNumber() + 1
            results.close()
            return total
        }
    }

    /**
     * Executes and returns a PagedList for a JPAQL Query
     */
    public PathKeyMapPagedList list(CharSequence queryString, Map params, Map args) {
        def template = hibernateTemplate
        args = new HashMap(args)
        Integer maxCount = args.max as Integer
        params = new HashMap(params)

        if(queryString instanceof GString) {
            queryString = buildNamedParameterQueryFromGString((GString) queryString, params)
        }

        List dataList = template.execute { Session session ->
            Query q = (Query) session.createQuery(queryString.toString())
            template.applySettings(q)

            populateQueryArguments(q, params)
            populateQueryArguments(q, args)
            populateQueryWithNamedArguments(q, params)
            //sets the transformer to remove the _sum, _avg, etc.. systemAliases
            //q.setResultTransformer(new AliasProjectionResultTransformer(systemAliases))
            q.setResultTransformer(new PathKeyMapResultTransformer(systemAliases))

            def qry = createHqlQuery(session, q)
            def list = qry.list()
            return list
        }
        //only do the count query if its needed
        int rowCount = dataList.size()
        if(rowCount > 1 && maxCount && rowCount >= maxCount){
            rowCount = countQuery(queryString, params)
        }
        PathKeyMapPagedList pagedList = new PathKeyMapPagedList(dataList, rowCount)
        return pagedList
    }

    @CompileDynamic //get around the protected
    HibernateHqlQuery createHqlQuery(Session session, Query q)  {
        return staticApi.createHqlQuery(session, q)
    }

    @CompileDynamic //get around the protected
    void populateQueryArguments(Query q, Map args)  {
        staticApi.populateQueryArguments(q, args)
    }

    @CompileDynamic //get around the protected
    void populateQueryWithNamedArguments(Query q, Map queryNamedArgs)  {
        staticApi.populateQueryWithNamedArguments(q, queryNamedArgs)
    }

    @CompileDynamic //get around the protected
    String buildNamedParameterQueryFromGString(GString query, Map params) {
        return staticApi.buildNamedParameterQueryFromGString(query, params)
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy