pbarker
03/31/2025, 6:29 PMclass Grandparent {
static hasMany = [ parents:Parent ]
}
// Joins the 'Child' instances to the 'Grandparent' instance.
class Mother extends Parent {
static belongsTo = [ grandparent:Grandparent ]
}
// The superclass that holds the 'Child' instances.
class Parent {
static hasMany = [ children:Child ]
}
class Child {
belongsTo = [
mother:Parent
]
}
So to find all the Child instances that belong to a particular Grandparent (via the Mother), I assumed I could do:
def c = Child.createCriteria()
def children = c.list {
mother {
grandparent {
eq('id', 1L) // Looking Grandparent[1].
}
}
}
But it keeps complaining about No signature of method grandparent.call().
I'm guessing it's because 'mother' is not an actual Hibernate table whereas 'Parent' is the actual table. But I don't have a 'parent' property in the Child...
Should I be looking at aliases, to try and encourage the query to look at the right column?
Any ideas?jeffscottbrown
03/31/2025, 6:38 PMjeffscottbrown
03/31/2025, 6:43 PMbelongsTo=[mother:Parent} to belongsTo=[mother:Mother]?pbarker
03/31/2025, 6:44 PMjeffscottbrown
03/31/2025, 6:44 PMpbarker
03/31/2025, 6:49 PMdef c = Child.createCriteria()
def children = c.list {
mother {
eq('grandparent.id', 1L) // Looking Grandparent[1].
}
}jeffscottbrown
03/31/2025, 6:50 PMjeffscottbrown
03/31/2025, 6:50 PMpbarker
03/31/2025, 6:50 PMpbarker
03/31/2025, 6:51 PMjeffscottbrown
03/31/2025, 6:51 PMjeffscottbrown
03/31/2025, 7:00 PMpbarker
03/31/2025, 7:00 PMjeffscottbrown
03/31/2025, 7:00 PMpbarker
03/31/2025, 7:03 PMgaolei
04/01/2025, 2:05 AMclass Grandparent {
static hasMany = [ parents:Parent ]
}
// Joins the 'Child' instances to the 'Grandparent' instance.
class Mother extends Parent {
static belongsTo = [ grandparent:Grandparent ]
}
// The superclass that holds the 'Child' instances.
class Parent {
static hasMany = [ children:Child ]
}
class Child {
belongsTo = [
mother:Parent
]
}
So to find all the Child instances that belong to a particular Grandparent (via the Mother), I assumed I could do:
def c = Child.createCriteria()
def children = c.list {
mother {
grandparent {
eq('id', 1L) // Looking Grandparent[1].
}
}
}
I'll analyze the code snippets you've provided and the query issue you're encountering.
The problem with your query is that the relationship structure in your domain model doesn't match the traversal path you're trying to use in the criteria query.
Looking at your class definitions:
1. Grandparent has many Parent objects
2. Mother (which extends Parent) belongs to a Grandparent
3. Parent has many Child objects
4. Child belongs to a Parent (specified as mother)
The issue is that in your criteria query, you're trying to navigate from Child ā mother ā grandparent, but your domain model doesn't establish this complete path. The Child class only has a relationship with Parent (via the mother property), not with Mother specifically, and there's no direct connection from Parent to Grandparent.
Here are a few approaches to fix this:
Option 1: If mother is always a Mother object (which has the grandparent association), you could use a type check:
groovy
def c = Child.createCriteria()
def children = c.list {
mother {
eq('class', Mother)
grandparent {
eq('id', 1L)
}
}
}
Option 2: Modify your domain model to better reflect the relationships:
groovy
class Child {
static belongsTo = [
mother: Mother // Change from Parent to Mother
]
}
Option 3: Use a join in your criteria query:
groovy
def c = Child.createCriteria()
def children = c.list {
createAlias('mother', 'm')
createAlias('m.grandparent', 'g')
eq('g.id', 1L)
}
Option 4: Use a more complex HQL query:
groovy
def children = Child.executeQuery("""
from Child c
where c.mother in (
from Mother m where m.grandparent.id = :grandparentId
)
""", [grandparentId: 1L])
The key issue is that your object model and the query path don't align correctly. The relationship from Child to Grandparent via Mother needs to be properly established in both the domain model and the query.pbarker
04/01/2025, 10:10 AMeq('class', Mother) to filter out the gaps so I'll definitely give that a try.
But I'm currently having trouble with createAlias() . Not sure if this is a separate question but it looks to me like Hibernate's CriteriaImpl.java isn't creating the alias.
My alias statements:
createAlias('rfxQuestion', 'questionAlias', JoinType.LEFT_OUTER_JOIN)
createAlias('questionAlias.note', 'noteAlias', JoinType.LEFT_OUTER_JOIN)
or {
ilike('name', filters.search)
ilike('questionAlias.noteAlias.html', filters.search)
}
Trouble is, I'm getting could not resolve property: questionAlias.
Stepping it through, it's hitting createAlias in org.hibernate.internal.CriteraImpl.java which looks like this:
@Override
public Criteria createAlias(String associationPath, String alias, JoinType joinType) {
new Subcriteria( this, associationPath, alias, joinType );
return this;
}
Which isn't actually returning the new Subcriteria. I don't really class myself as a Java developer but this doesn't look right to me! I must be missing something...pbarker
04/01/2025, 10:34 AMcreateAlias('rfxQuestion', 'questionAlias', CriteriaSpecification.LEFT_JOIN)
createAlias('questionAlias.note', 'noteAlias', CriteriaSpecification.LEFT_JOIN)
or {
ilike('name', filters.search)
ilike('noteAlias.html', filters.search)
}
⢠Using CriteriaSpecification instead of JoinType (even though it's deprecated and returns a JoinType anyway...)
⢠Only reference the last alias in the chain in the ilike statement. I was previously referencing the whole chain.gaolei
04/01/2025, 3:07 PMpbarker
04/01/2025, 3:09 PMpbarker
04/01/2025, 3:10 PMpbarker
04/01/2025, 3:11 PMpbarker
04/01/2025, 3:13 PMgaolei
04/01/2025, 3:13 PMgaolei
04/01/2025, 3:14 PMpbarker
04/01/2025, 3:16 PMgaolei
04/01/2025, 3:16 PMpbarker
04/01/2025, 3:17 PMgaolei
04/01/2025, 3:17 PMpbarker
04/01/2025, 3:19 PMgaolei
04/01/2025, 3:21 PM