任務是支持用戶名被存儲在數據庫中,因爲它們最初是在創建時鍵入的,並且使用'ilike'準則檢查唯一性'eq'。編寫一個必須在命令對象和域對象上工作的自定義grails唯一約束
在挖掘中,我看到了2個實現UniqueConstraint
,其中一個由grails-datastore-gorm提供,另一個由grails-hibernate提供。我知道我需要在一個塊中執行這個查找,因爲我在會話對象上重置了FlushMode
,所以hibernate在數據驗證之前不會將更改保存到數據庫。這是我寫的自定義的驗證:
@Override
protected void processValidate(final Object target, final Object propertyValue, Errors errors) {
def reject = false
doWithManualSessionIfAppropriate {
def targetId = null
try {
targetId = InvokerHelper.invokeMethod(target, 'ident', null)
} catch (Exception e) {
throw new GrailsRuntimeException('Could not determine id of target')
}
def results = []
results += constraintOwningClass."findAllBy${GrailsNameUtils.getClassName(constraintPropertyName, '')}Ilike"(propertyValue)
reject = results.any {
try {
def existingId = InvokerHelper.invokeMethod(it, 'ident', null)
targetId != existingId
} catch (Exception e) {
// the existing field is not in the db
false
}
}
}
if (reject) {
errors.rejectValue(constraintPropertyName, 'unique')
}
}
這讓我們的集成測試都通過了,但是當我在調用importFrom
來驗證用戶名控制器中使用它,invokeMethod
未能找到命令對象的ID。例如:
RealUser.groovy:
class RealUser {
String username, passwordHash
static constraints = {
username iunique: true // where iunique is the name of my registered constraint
}
}
UserController.groovy:
@Validateable
class UserCommandObject {
String username, password, passwordConfirmation
static constraints = {
importFrom RealUser
}
}
當我對RealUser
unique: true
,驗證就好了UserCommandObject
。當我將其更改爲我的自定義驗證程序iunique: true
時,UserCommandObject
抱怨說它不是域類。
我不可能看到unique: true
如何用於命令對象,因爲我看到的兩個實現只能在域對象上工作(並且在沒有域對象時調用GrailsRuntimeException
)。
任何想法?我在想這個太過分了嗎?
從另一個角度接近,沒有任何令人信服的理由不支持存儲用戶名作爲輸入的,只是呼籲輸入驗證lower()
之前?