gorm projection and loss of metainformation
Asked Answered
M

2

8

When using projection on the properties, the result is returned as the list with the elements in the same sequence as that defined in the projections block. At the same time the property names are missing from the list and that is really disadvantageous to the developer as the result would be passed along and the caller needs to know what value belongs to which property. Is there a way to return a map from the Criteria query with property name as the key to the value?

so, the following code:

def c = Trade.createCriteria()
def remicTrades = c.list {

    projections {
        property('title', 'title')
        property('author.name', 'author')
    }
    def now = new Date()
    between('publishedDate', now-365, now)
}

This returns:

[['book1', 'author1']['book2', 'author2']]

Instead I would like it to return:

[[book:'book1', author:'author1'][book:'book2', author:'author2']]

I know I can arrange this way after getting the result but I earnestly feel that the property alias should have been used by the criteria to return a list of map that mimics the result of the SQL query and not a bland list.

Mcfarlane answered 7/11, 2012 at 0:40 Comment(1)
Agree, having a map would be immensely helpful.Maloy
C
8

Duplicate: Grails queries with criteria: how to get back a map with column?
And the corresponding answer (and solution): https://mcmap.net/q/796916/-grails-queries-with-criteria-how-to-get-back-a-map-with-column

Use resultTransformer.

import org.hibernate.criterion.CriteriaSpecification

Trade.withCriteria {
  resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)
  projections {
    property('title', 'title')
    property('author.name', 'author')
  }
  def now = new Date()
  between('publishedDate', now-365, now)
}     
Casabonne answered 7/5, 2013 at 0:59 Comment(0)
M
1

Agree with your question reasoning, this really should be part of the core GORM solution. That said, here's my workaround;

def props = ['name','phone']
def query = Person.where {}.projections {
        props.each{
                property(it)
        }

}
def people = query.list().collect{ row->
        def cols = [:]
        row.eachWithIndex{colVal, ind->
            cols[props[ind]] = colVal
        }
        cols
}
println people // shows [['name':'John','phone':'5551212'],['name':'Magdalena','phone':'5552423']]
Maloy answered 18/11, 2012 at 5:49 Comment(1)
grails could perform this mapping and uphold the DRYMcfarlane

© 2022 - 2024 — McMap. All rights reserved.