我通常将连接表映射为域类以避免此问题和其他问题(集合加载性能、乐观锁定错误等)。这涉及删除hasMany
和belongsTo
创建CustomerRole
域类:
import org.apache.commons.lang.builder.HashCodeBuilder
class CustomerRole implements Serializable {
Customer customer
Role role
boolean equals(other) {
if (!(other instanceof CustomerRole)) {
return false
}
other.customer?.id == customer?.id &&
other.role?.id == role?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (customer) builder.append(customer.id)
if (role) builder.append(role.id)
builder.toHashCode()
}
static CustomerRole get(long customerId, long roleId) {
find 'from CustomerRole where customer.id=:customerId and role.id=:roleId',
[customerId: customerId, roleId: roleId]
}
static CustomerRole create(Customer customer, Role role, boolean flush = false) {
new CustomerRole(customer: customer, role: role).save(flush: flush, insert: true)
}
static boolean remove(Customer customer, Role role, boolean flush = false) {
CustomerRole instance = CustomerRole.findByCustomerAndRole(customer, role)
instance ? instance.delete(flush: flush) : false
}
static void removeAll(Customer customer) {
executeUpdate 'DELETE FROM CustomerRole WHERE customer=:customer', [customer: customer]
}
static void removeAll(Role role) {
executeUpdate 'DELETE FROM CustomerRole WHERE role=:role', [role: role]
}
static mapping = {
id composite: ['customer', 'role']
version false
table 'customer_roles'
}
}
映射块配置生成的 DDL,因此它与您现在拥有的相同,因此您不需要进行任何数据库更改。静态辅助方法不是必需的,但可以方便地隐藏授予和撤销角色的过程。
您将需要更改代码。既然没有hasMany
,你就不能使用customer.addToRoles(...)
。而不是授予角色,只需使用该方法创建一个新的 CustomerRole 实例,create
然后使用该方法撤消、删除该实例remove
。
更新的角色类将是
class Role {
}
更新后的 Customer 类将是
class Customer {
Set<Role> getRoles() {
CustomerRole.findAllByUser(this).collect { it.role } as Set
}
}
这有一个方便的方法getRoles()
,它模仿了roles
为您创建的集合,hasMany
因为您仍然需要一种简单的方法来访问客户的授予角色。