简体   繁体   中英

Grails Domain Create Association Table

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 lastUpdated
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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM