вы должны быть в состоянии уйти с
static constraints = {
addresses(validator: checkAddress)
}
// This is a static method which is used for validation
// and can be used for when inserting a record to check how many
// existing addresses exist for the end user that has countryCode of US
// This is directly bound to all the object the user and will
// will not be searching the entire DB (A local find limited to user records)
static def checkAddress={val,obj,errors->
if (!obj?.addresses.findAll{it.countryCode=='US'}?.size() >= 2) {
return errors.rejectValue('adress','exceeds limit')
}
}
Вышеизложенное должно быть самоочевидным, но, прочитав ваш пост несколько раз, я думаю, что лучше понимаю, чего вы пытаетесь достичь, и, вероятно, есть несколько разных способов сделать это. Итак, давайте рассмотрим некоторые из них:
Используя запрос HQL, вы можете изменить его на другой метод, я предпочитаю HQL.
class Customer {
def userService
//UserAddress does not have setter transients not essential
static transients = ['userAddress','userService']
//This is a protected function that will return an address
// object given a countryCode
// Execute like this:
// Customer cm = Customer.get(customer.id as Long)
//Address usa = cm.getCountry('US')
protected Address getUserAddress(String countryCode) {
return userService.findAddress(countryCode, this.id)
}
}
Теперь служба, но на самом деле вам не нужно выполнять в классе домена, если нет какой-либо другой необходимости, для отображения и т. д. вы всегда можете вызвать этот вид службы из вызова контроллера для отображения для целей отображения
class UserSerice {
// This should return the entire address object back to the domain class
// that called it and will be quicker more efficient than findAll
Address findAddress(String countryCode, Long customerId) {
String query="""
select address from Address a
where a.id :id and countryCode = :code
"""
def inputParams=[code:countryCode, id:customerId]
return Address.executeQuery(query,inputParams,[readOnly:true,timeout:15])
}
Другим подходом может быть третья таблица, которая обновляется при каждом добавлении адреса, что даст быстрый поиск:
class Customer {
static hasMany = [
addresses: Address
//probably don't even need this
//, userCountries:UserCountries
]
}
Class UserCountries {
// register customer
Customer customer
String CountryCode
//maybe address object or Long addressId - depending on if how plain you wanted this to be
Address address
}
Затем регистрируйте идентификатор адреса и код страны в этом доменном классе каждый раз, когда вы добавляете новый адрес, и я думаю, вам нужно будет написать некоторый обратно совместимый код, чтобы добавить существующие записи в эту таблицу, чтобы она работала правильно.
Я оставил комментарий, а затем удалил его, чтобы вы могли подробнее рассказать о том, что и как происходило фильтрование. поскольку, хотя вы говорите о коде страны, нет фактического кода, показывающего, как все это вписывается.
Я все еще думаю, что что-то настолько простое, как это, сработает // Это будет только поиск со всеми связанными объектами адресов, привязанными к этому клиенту. поэтому найдите в элементах отношения hasMany этого конкретного клиента
protected def getCustomAddress(String countryCode) {
return addresses.findAll{it.code==countryCode}
}
Другие далекие идеи могут быть чем-то вроде этого
class Customer {
String _bindAddress
List bindAddress=[]
static transients = [ 'bindAddress' ]
static constraints = {
_bindAddress(nullable:true)
}
//you store a flat CSV as _bindAddress
//you need to work out your own logic to ammend to existing CSV each time address is added
// you will also update _bindAddress of this domainClass each time customer gets a hasMany address added
// so no need for setBindAddress
// void setBindAddress(String b) {
// bindAddress=b.split(',')
// }
//Inorder to set a list back to flat file
//pass in list object
void setBindAddress(List bindAddress) {
_bindAddress=bindAddress.join(',')
/for 1 element this captures better
//_bindAddress=bindAddress.tokenize(',').collect{it}
}
//This is now your object as a list that you can query for what you are querying.
List getBindAdress() {
return _bindAddress.split(',')
}
}
Если ваш фактический список csv содержал список «COUNTRY_CODE-ADDRESS_ID», вы могли бы запросить, как это
def found = customer.bindAddress.find{it.startsWith('US-')}
Address usaAddress= Address.get(found.split('-')[1] as Long)
//Slightly longer explaining above:
def found = customer.bindAddress.find{it.startsWith('US-')}
def record = found.split('-')
String countryCode=record[0]
Long addressId=record[1] as Long
Address usaAddress= Address.get(addressId)
person
V H
schedule
14.06.2016