任务是支持用户名被存储在数据库中,因为它们最初是在创建时键入的,并且使用'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()
之前?