1

我正在使用带有默认 h2 数据库的 grails 2.0.3 并具有以下用户域类:

class User {
    transient springSecurityService

    String username
    String password
    boolean enabled
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired

    Preferences preferences
    Company company
    Personal personal

    static constraints = {
        username    email: true, blank: false, unique: true
        password    blank: false
        preferences unique: true
        company     unique: true
        personal    unique: true
    }

    static mapping = {
        password column: '`password`'
    }

    Set<Role> getAuthorities() {
        UserRole.findAllByUser(this).collect { it.role } as Set
    }

    def beforeInsert() {
        encodePassword()
    }

    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }

    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
}

在控制器中,我使用以下代码保存用户:

userInstance.save(flush: true)

现在,今天下午,我意识到密码字段应该有一个大小约束,因此修改了域类,使其如下(仅更改在约束中):

class User {
    transient springSecurityService

    String username
    String password
    boolean enabled
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired

    Preferences preferences
    Company company
    Personal personal

    static constraints = {
        username    email: true, blank: false, unique: true
        password    blank: false, size: 6..15
        preferences unique: true
        company     unique: true
        personal    unique: true
    }

    static mapping = {
        password column: '`password`'
    }

    Set<Role> getAuthorities() {
        UserRole.findAllByUser(this).collect { it.role } as Set
    }

    def beforeInsert() {
        encodePassword()
    }

    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }

    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
}

随后我再次生成了视图和控制器。现在,当我尝试从控制器中保存用户对象时,使用:

userInstance.save(flush: true)

我收到以下异常:

类:org.hibernate.AssertionFailure 消息:login.User 条目中的空 id(发生异常后不要刷新 Session)

任何帮助将不胜感激。

信息:如果我从新的/修改的类中删除大小约束,保存会很好。

4

1 回答 1

-1

我在使用 Grails 3.1.12 时遇到了同样的问题。这就是我发现的以及我如何解决它的。

问题:

您正在尝试对将要进行编码的字段进行大小限制。这意味着像“admin5”这样的密码将在域生命周期结束时变成编码密码。例如,数据库将密码存储为:“$2a$10$dn7MyN.nsU8l05fMkL/rfek/d1odko9H4QUpiNp8USGhqx9g0R6om”。

验证过程会将大小约束应用于未编码的密码(域生命周期的验证步骤),因为用户输入的密码在该范围内,所以将通过。但是在 save() 方法(域生命周期的持久性步骤)上,密码将在插入或更新之前进行编码。enconding 方法将创建一个大小大于约束的 pwd,并且 Hibernate 将使 pwd 大小的 assert() 失败。

解决方案:

如果您不需要担心 maxSize,请使用 minSize 约束

 static constraints = {
    password    blank: false, minSize:6
}

如果您需要验证 maxSize,那么我建议您在创建域实例之前对您的服务或控制器层进行验证。

于 2016-09-28T23:51:42.410 回答