views:

245

answers:

1

Hi, I have 2 domain classes

class A {
  ....
  static hasMany = [bs:B]
}
class B {
  int code
  ....
}

How can I list the number of ocurrences of all codes in B in all the A table?

Something like

b.each { thisb ->
  int ocurrences = A.bs.findAll{it == thisb}.size()
  ...
}

Thanks

+2  A: 

I think the reason that I'm a little confused by this question is that technically it's actually a many-to-many relationship, not really a one-to-many. Grails will create a join table ("a_b") for this relationship (because B doesn't have a belongsTo relationship to A).

The way you have your A domain constructed the hasMany relationship is a set, so B will only appear a single time in the "bs" collection. So, I believe, all you're asking is how many As have a B.

If thats true, you can use HQL to answer your question (you can also use criteria builders, but I prefer hql). Here's an example (using the build-test-data plugin to construct objects with buildLazy and adding a String name to A):

def a1 = A.buildLazy(name: "one")
def a2 = A.buildLazy(name: "two")
def a3 = A.buildLazy(name: "three")
def a4 = A.buildLazy(name: "four")

def b1 = B.buildLazy(code: 888)
def b2 = B.buildLazy(code: 999)

a1.addToBs(b1)
a2.addToBs(b1)
a3.addToBs(b1)
a4.addToBs(b1)

a1.addToBs(b2)

println "Number of As that have each B = " + 
    A.executeQuery("select count(b), b.code from A as a join a.bs as b group by b.code")

println "Number of As with a specific B = " + 
    A.executeQuery("select count(*) from A as a join a.bs as b where b = :b", [b: b1])

results in:

Number of As that have each B = [[1, 999], [4, 888]]
Number of As with a specific B = [4]
Ted Naleid
Actually no, it's one to many; there can be at most the number of rows in A of Bs assuming every A has a given B. I already implemented it with a couple of "each" loops, what I wanted to know is if there's a GORMy way for doing this ( with .findBy*, .count*, etc).
xain
@Xain technically, there's nothing restricting this to One To Many... you most certainly CAN create many Bs and have them all be children of the each and every A you create. To restrict it, you'd need to add a belongsTo line in B.
Bill James
Right, without a belongsTo, the db model that gets generated has a join table. Even if you're restricting it from a logical standpoint, it really is a many to many without belongsTo. I'm not saying you've modeled it wrong. If B is a "code" table and A can have many Bs, this is the right way to model it to not have redundant Bs.You can't do it with the dynamic finders (findBy*, countBy*, etc), you'd have to use a criteria or hql as I used above. They don't work across hasMany relationships.
Ted Naleid