Динамические искатели с отношением Grails ко многим ко многим - PullRequest
2 голосов
/ 01 июля 2011

У меня есть 2 класса домена, которые сопоставлены отношением «многие ко многим».Я следовал инструкциям документации Grails, но у меня все еще есть некоторые проблемы при обработке данных в этих доменах.Вот мои 2 класса доменов:

class User {
    String name
    int age
    String job
    static hasMany = [groups : Group]
    static belongsTo = [org : Organization]
}

class Group {
    String groupName
    String code
    static hasMany = [members : User]
}

Мои проблемы:
1. Приведенные выше отношения требуют, чтобы один класс удерживал принадлежащий, чтобы быть "владельцем" отношения.В этом контексте Пользователь принадлежит к Группе, но я не знаю, как поместить принадлежность к классу Пользователя, потому что стандартный синтаксис, который предлагает Grails, является статическим принадлежащим = Группа (просто укажите имя класса владельца), поэтому яНевозможно:
- поместить его в существующую принадлежность, например: статическую принадлежность, = = [org: Organization, Group]
- или определить другую принадлежность, например: статическую принадлежность, = = [группа]

Ниже приведен пример справа:

class Book {Строка title static staticTo = Author static hasMany = [авторы: Author]

static mapping = {
    authors joinTable:[name:"mm_author_books", key:'mm_book_id' ]
}

} Класс Author {String name statichasMany = [books: Book]

static mapping = {
    books joinTable:[name:"mm_author_books", key:'mm_author_id']
}

}

(Ссылка: Таблицы ссылок «многие ко многим» в Grails (GORM) / hibernate))
Я имею в виду, что нам нужно указывать имя внешнего ключа таблицы соединения для каждого класса?

Если я хочу найти всех пользователей, которые являются членами указанной группы с именем «ABC», как я могу использовать DynamicFinder of Grails?

Большое вам спасибо

Ответы [ 2 ]

6 голосов
/ 01 июля 2011

Очень редко отношения m2m имеют собственную сторону, поэтому я всегда считал странным указывать одну для правильной работы GORM.Из-за этого я так не делаю.Я создаю таблицу соединений в качестве домена.Тогда все становится действительно простым.

class UserGroup implements Serializable {

    User user
    Group group

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

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

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

    static UserGroup get(long userId, long groupId) {
        find 'from UserGroup where user.id=:userId and group.id=:groupId',
            [userId: userId, groupId: groupId]
    }

    static UserGroup create(User user, Group group, boolean flush = false) {
        new UserGroup(user: user, group: group).save(flush: flush, insert: true)
    }

    static boolean remove(User user, Group group, boolean flush = false) {
        UserGroup instance = UserGroup.findByUserAndGroup(user, group)
        instance ? instance.delete(flush: flush) : false
    }

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

    static void removeAll(Group group) {
        executeUpdate 'DELETE FROM UserGroup WHERE group=:group', [group: group]
    }

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

Тогда вам просто нужно создать геттеры в вашем классе User и Group.У вас не будет пользователя или группы в любом классе.Нет необходимости сопоставлять их с hasMany / ownTo, потому что все, что нужно будет сделать, - это создать таблицу соединений, которую вы сделали, создав домен UserGroup.используйте методы, которые вы создали в домене UserGroup, и / или вы можете использовать в нем средства поиска ...

def userGroupInstance = UserGroup.findByUserAndGroup(userInstance, groupInstance)
def userGroups = UserGroup.findAllByUser(userInstance)
def userGroupInstance = UserGroup.get(userId, groupId)

Вы поняли идею.Эта презентация , написанная Бертом Беквитом , проливает больше света на то, почему это хороший подход, наряду с некоторыми другими полезными советами по повышению производительности.

0 голосов
/ 01 июля 2011
  1. belongsTo создаст еще одно отношение M: 1 (поле) - вы сообщаете, есть ли в вашем случае "основная группа" для User.Если бы я хотел использовать только одну группу, я бы пошел с пользовательским валидатором для User.groups проверки, что он не пустой.

  2. (я не уверен здесь) - яверьте да, если имя ключа отличается от имени по умолчанию Hibernat / GORM "userId" / "groupId".

  3. findBy*() методы не будут работать здесь, вам нуженCriteriaBuilder, например здесь .

...