你应该能够
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])
}
另一种方法可能是被在每个地址更新补充说,将给予快速查找第3表:
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
}
然后registe在每次添加新地址时将地址ID和countryCode添加到此域类中,我想您需要编写一些向后兼容的代码以将现有记录添加到此表以使其正常工作。
我留下了一条评论,然后将其删除,以便进一步扩展过滤发生的方式或过程。因为虽然你谈到的国家代码没有实际的代码来显示它是如何适合的。
我仍然认为这样简单的工作 //这只会做一个查找与地址的所有绑定对象绑定到这个客户。所以这个特定客户
protected def getCustomAddress(String countryCode) {
return addresses.findAll{it.code==countryCode}
}
其他深远的思路的的hasMany关系要素中的发现可能是这样的
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)
约束如何帮助我实现过滤功能(例如获取美国客户的所有地址)? 'checkAddress'只验证'addresses'和'checkAddress2'' findAllByCustomer'中不超过2个对象是不可能的,因为'Address'没有'customer'字段 – Andreas
obj?.addresses.findAll {it.country = ='美国'}?可能。 @Andreas – Vahid
这实际上是一个问题,这样做的缺点是集合的所有对象(在本例中为地址)从数据库中获取 – Andreas