My problem should be obvious, but I just don't see the light right now :-(
I have two domainclasses like this:
class Parent {
String name
static hasMany = [children: Child]
}
class Child {
String开发者_高级运维 name
}
Now I should be able to find the Parent of a child by using the dynamic finder of the Parent like:
Parent.findByChildren([someChild] as Set)
But I get a hibernate error stating that I've got a grammar error in my hibernate SQL:
Caused by: java.sql.SQLException: No value specified for parameter 1
And for the reference: someChild IS a concrete instance. And I would like to avoid Child to have an explicit parent in the definition.
How then can I go from the Child to the Parent?
Best Regards,
Christian Sonne Jensen
Just to end this question, I wanted to report a solution to my "problem". I'm using a namedQuery in the Parent entity (Customer or Producer) like this:
Class Customer {
static hasMany = [channels: Channel]
static namedQueries = {
findByChannel {
channelId ->
channels {
eq 'id', channelId
}
}
}
}
Then I find the Customer like this:
def customers = Customer.findByChannel(channel.id).list()
In this way the Channel are relieved of the burden of knowing anything about who references it, and I don't have to do any artificial relationship tables.
I still think that it must be some kind of mistake that I cannot use one of the dynamic finders:
Customer.findByChannels([channel] as Set)
Maybe the dynamic finders doesn't take one-to-many relationsships into account, and only works for simple attributes??? (I'm using Grails 1.3.1)
Thanks for your replies though!
Christian Sonne Jensen
If you don't want the parent foreign key on the child, you'll have to create a join table for the parent that serves as a surrogate for the child:
class ParentalRelationship {
static belongsTo = [parent: Parent, child: Child]
}
You could then have helper methods on the parent to query for children through the ParentalRelationship object.
With your real implementation of Customers, Channels, and Producers, chances are that you'd want a many-to-many relationship anyways as a channel wouldn't belong to a single customer (or a single producer).
Maybe a better way is to write in the chield
the belongsTo
something like this:
static belongsTo = [parent: Parent]
And then you can use:
Chield c = ...
Parent parent = c.parent
I would invert it:
class Parent {
String name
static Set<Child> getChildren() {
Child.findAllByParent(this) as Set
}
}
class Child {
String name
Parent parent
}
This uses the same database structure (the child table has a foreign key to parent) but makes it easy to go from one side to the other without being explicitly bidirectional.
One thing does change. Instead of this:
def parent = ...
parent.addToChildren(new Child(...))
parent.save()
you do this:
def parent = ...
def child = new Child(parent: parent, ...).save()
This is more performant because you don't need to load the entire collection just to persist a new child.
精彩评论