Sie sollten mit
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')
}
}
Die oben sollte selbsterklärend, aber gelesen zu durch Ihren Beitrag ein paar Mal jetzt wegzukommen der Lage sein, ich glaube, ich habe ein besseres Verständnis von dem, was Sie versuchen, zu erreichen und es gibt wahrscheinlich ein paar verschiedene Möglichkeiten, es zu tun. Also lassen Sie uns einige von ihnen erkunden:
Mit HQL-Abfrage können Sie dies zu einer anderen Methode ändern, bevorzuge ich 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)
}
}
Jetzt ist der Service aber eigentlich brauchen Sie nicht in Domain-Klasse auszuführen, es sei denn es eine andere Notwendigkeit ist, für die Anzeige usw. Sie immer diese Art von Service aus einem Controller Anruf nennen könnte für die Anzeige zu machen
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])
}
ein anderer Ansatz könnte eine dritte Tabelle, die die eine schnelle Suche geben würde hinzugefügt bei jeder Adresse aktualisiert wird:
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
}
Dann Registe Wenn Sie eine neue Adresse hinzufügen, müssen Sie die Adress-ID und den Ländercode an diese Domänenklasse anhängen, und ich denke, Sie müssten rückwärtskompatiblen Code schreiben, um dieser Tabelle vorhandene Datensätze hinzuzufügen, damit sie ordnungsgemäß funktionieren.
Ich hinterließ einen Kommentar und entfernte ihn dann für Sie weiter zu erweitern, was oder wie die Filterung stattfand. da, obwohl Sie von country sprechen es kein tatsächlicher Code ist zu zeigen, wie sie paßt alles in.
Ich denke immer noch etwas so einfach wie diese funktionieren würde // Dies wäre ein nur mit all gebundenen Objekten von Adressen finden tun an diesen Kunden gebunden.so ein Fund innerhalb der hasMany Beziehung Elemente dieses spezifischen Kunden
protected def getCustomAddress(String countryCode) {
return addresses.findAll{it.code==countryCode}
}
Andere weit Ideen könnte so etwas wie diese
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(',')
}
}
sein, wenn Ihre tatsächliche CSV-Liste eine Liste von ‚COUNTRY_CODE-ADDRESS_ID‘ enthält dann Sie könnten so abfragen
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)
Wie könnte eine Einschränkung mir helfen, eine Filterfunktion zu implementieren (zum Beispiel erhalten alle Adressen eines Kunden in den USA)? 'checkAddress' validiert nur, dass dort nicht mehr als 2 Objekte in' addresses' und in 'checkAddress2'' findAllByCustomer' nicht möglich sind, da 'Address' kein' customer' Feld hat – Andreas
obj? .addresses.findAll {it.country = = "US"}? möglicherweise . @Andreas – Vahid
Dies ist eigentlich die Frage, der Nachteil davon ist, dass alle Objekte der Sammlung (in diesem Fall Adressen) aus der Datenbank – Andreas