Grails动态查找器很多
我有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.上述关系要求一个类别拥有belongsTo作为关系的“所有者”。 在这种情况下,用户属于Group,但我不知道如何将belongsTo设置为User类,因为Grails建议的标准语法是static belongsTo = [Group](只需指定所有者类名),所以我不能:
- 把它放到存在所属的地方就像这样:static belongsTo = [org:Organization,Group]
- 或者定义另一个belongsTo就像这样:static belongsTo = [Group]
下面的例子是对的:
class Book {String title static belongsTo =作者static hasMany = [作者:作者]
static mapping = {
authors joinTable:[name:"mm_author_books", key:'mm_book_id' ]
}
} class Author {String name static hasMany = [books:Book]
static mapping = {
books joinTable:[name:"mm_author_books", key:'mm_author_id']
}
}
(引用链接:grails(GORM)/ hibernate中的多对多链接表)
我的意思是,我们是否需要为每个类指定连接表的外键的名称?
非常感谢
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类中创建getter。 您将不会在任何一个班级中拥有User用户或Group组。 没有必要将它们与hasMany / belongsTo进行映射,因为所做的只是创建连接表,这通过创建UserGroup域来完成。
class User {
Set<Group> getGroups() {
UserGroup.findAllByUser(this).collect { it.group } as Set
}
}
class Group {
Set<User> getUsers() {
UserGroup.findAllByGroup(this).collect { it.user } as Set
}
}
一旦你有了这些,你可以使用你在UserGroup域创建的方法和/或你可以使用它的发现者...
def userGroupInstance = UserGroup.findByUserAndGroup(userInstance, groupInstance)
def userGroups = UserGroup.findAllByUser(userInstance)
def userGroupInstance = UserGroup.get(userId, groupId)
你明白了。 Burt Beckwith的这个演示更清晰地说明了为什么这是一个很好的方法,以及一些其他的提高性能的重要技巧。
belongsTo
将创建另一个M:1关系(字段) - 您告诉您的案例中是否有User
的“主要组”。 如果我只希望强制执行至少一个组,那么我会使用User.groups
的自定义验证程序检查它是否为空。
(我不确定) - 我相信是,如果密钥名称不同于默认的Hibernat / GORM“ userId
”/“ groupId
”。
findBy*()
方法在这里不起作用,你需要一个CriteriaBuilder,就像这里。