【问题标题】:Writing a custom grails unique constraint that must work on command objects and domain objects编写必须对命令对象和域对象起作用的自定义 grails 唯一约束
【发布时间】:2014-03-03 23:24:34
【问题描述】:

任务是支持将用户名存储在数据库中,因为它们最初是在创建时键入的,并使用“ilike”标准代替“eq”来检查唯一性。

在挖掘过程中,我看到了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()

【问题讨论】:

    标签: grails groovy grails-orm


    【解决方案1】:

    自定义验证器中的 findByPropertyNameIlike(val) 能解决问题吗?

    static constraints = {
        propertyName blank: false, validator: { val, obj, errors ->
    
            def results = this.findByPropertyNameIlike(val)
    
            if(results) {
                errors.rejectValue('propertyName', 'unique.propertyName')
                return false
            }
    
            return true
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-07
      • 1970-01-01
      • 2019-12-19
      • 2013-03-03
      相关资源
      最近更新 更多