Обычно я сопоставляю таблицу соединений как класс домена, чтобы избежать этой и других проблем (производительность загрузки коллекции, ошибки оптимистической блокировки и т. Д.). Это включает удаление 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
, поскольку вам все еще понадобится простой способдля доступа к предоставленным ролям клиента.