开发者

Grails Domain Create Association Table

开发者 https://www.devze.com 2023-03-25 03:57 出处:网络
I have a question about creating an associative table, in grails, to reconcile a many-to-many relationship.The setup is this:

I have a question about creating an associative table, in grails, to reconcile a many-to-many relationship. The setup is this: 1. Domain A (Client Profile) can have many Domain B (Friends) 2. Each Domain B (Friends) can have many Domain A (Client Profile) 3. To Resolve this, I need to create an Associative table (or domain) that has FK's from each table. This domain can be named Domain C (client_friend)

Here is the code I have so far:

class DomainA{
    String id
String firstName
String lastName
    static hasMany = [domainB: DomainB]
    static mapping = {
    cache true
    id generator: 'assigned'

    columns {
        firstName   type:'text'
        lastName    type:'text'
        alumConnections column: 'domaina_id', joinTable: 'a_b'
    }

}
static constraints = {
    firstName   (nullable:true)
    lastName    (nullable:true)
}

  }

DomainB Code:

   class DomainB{   
String id
String firstName
String lastName

    static hasMany = [domainA:DomainA]
static belongsTo = DomainA
static mapping = {
    cache true
    id generator: 'assigned'        

             columns {                  
        firstName       type:'text'
        lastName        type:'text'
        domainA column: 'domainb_id', joinTable: 'a_b'
    }
}
static constraints = {  
    firstName       (nullable:true)
    lastName        (nullable:true)

}
  }

Domain A_B code:

 class AB{


Date dateCreated
Date lastUpdate开发者_Go百科d
long version

  }

When I run this code, it seems to work. The tables, using MySQL, are created, FK seem to be in place. When I enter data into the DomainB class, data is entered and both PK's from DomainA and DomainB are inserted into A_B. But, the problems comes when I try to delete values from A_B. I've tried something like this:

     AB results =AB.findByAIdAndBId('jIi-hRi4cI','2BYvuA2X14') 

but get an error: InvalidPropertyException: No property found for name [a_id] for class [class mgr.AB]

My question is this: first, have i set this up correctly? Second, if so, how then do i query the AB table who's PK is made up of a composite of DomainA and DomainB?

Thanks for any help.

jason


Your composite class isn't entirely correct. Look at this example and adjust yours accordingly. This is how I do all my composite domains:

class UserRole implements Serializable {

    User user
    Role role

    boolean equals(other) {
        if (!(other instanceof UserRole)) {
            return false
        }

        other.user?.id == user?.id &&
            other.role?.id == role?.id
    }

    int hashCode() {
        def builder = new HashCodeBuilder()
        if (user) builder.append(user.id)
        if (role) builder.append(role.id)
        builder.toHashCode()
    }

    static UserRole get(long userId, long roleId) {
        find 'from UserRole where user.id=:userId and role.id=:roleId',
            [userId: userId, roleId: roleId]
    }

    static UserRole create(User user, Role role, boolean flush = false) {
        new UserRole(user: user, role: role).save(flush: flush, insert: true)
    }

    static boolean remove(User user, Role role, boolean flush = false) {
        UserRole instance = UserRole.findByUserAndRole(user, role)
        instance ? instance.delete(flush: flush) : false
    }

    static void removeAll(User user) {
        executeUpdate 'DELETE FROM UserRole WHERE user=:user', [user: user]
    }

    static void removeAll(Role role) {
        executeUpdate 'DELETE FROM UserRole WHERE role=:role', [role: role]
    }

    static mapping = {
        id composite: ['role', 'user']
        version false
    }
}

Once you have that, there is no need for the belongsTo and hasMany associations. But to access the data from those domains, you can provide methods like the following:

class User {

   // typical domain junk

   Set<Role> getAuthorities() {
     UserRole.findAllByUser(this).collect { it.role } as Set
   }
}

Then you can do things like userInstance.authorites just as if the hasMany was there. Basically, you're doing what Grails would typical do for you. But this is actually a good thing. Collections in Grails can be costly if not done right. This is being addressed in 2.0 with the use of Bags.

0

精彩评论

暂无评论...
验证码 换一张
取 消