简体   繁体   English

Grails域类约束修改导致异常

[英]Grails domain class constraint modification causing exception

Am using grails 2.0.3 with default h2 database and have the following user domain class: 我在默认的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)
    }
}

In the controller, I save the user using the following code: 在控制器中,我使用以下代码保存用户:

userInstance.save(flush: true)

Now, this afternoon, I realized that the password field should have a size constraint and hence modified the domain class so that it became as follows (only change is in the constraints): 现在,今天下午,我意识到密码字段应该有大小限制,因此修改了域类,使其变为如下所示(仅更改了限制):

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)
    }
}

Subsequently I generated the views and controllers again. 随后,我再次生成了视图和控制器。 Now when I am trying to save the user object from the controller, using: 现在,当我尝试从控制器保存用户对象时,请使用:

userInstance.save(flush: true)

I am getting the following exception: 我收到以下异常:

Class: org.hibernate.AssertionFailure Message: null id in login.User entry (don't flush the Session after an exception occurs) 类:org.hibernate.AssertionFailure消息:登录中的id为null。用户条目(发生异常后不要刷新Session)

Any help will be appreciated. 任何帮助将不胜感激。

Info: If I remove the size constraint from the new/modified class the saving happens fine. 信息:如果我从新的/修改的类中删除了大小限制,则保存会很好。

I ran into the same problem using Grails 3.1.12. 我在使用Grails 3.1.12时遇到了同样的问题。 This is what I found out and how I solved it. 这就是我发现的以及如何解决的方法。

Problem: 问题:

You are trying to put a size constraint to a field that is going to be enconded. 您正在尝试将大小约束放到将要确认的字段上。 This means that a password like "admin5" will turn at the end of the domain life cycle as an encoded pwd. 这意味着像“ admin5”这样的密码将在域生命周期结束时以已编码的pwd身份出现。 For example the db will stored the pwd as: "$2a$10$dn7MyN.nsU8l05fMkL/rfek/d1odko9H4QUpiNp8USGhqx9g0R6om". 例如,数据库会将pwd存储为:“ $ 2a $ 10 $ dn7MyN.nsU8l05fMkL / rfek / d1odko9H4QUpiNp8USGhqx9g0R6om”。

The validation process will apply the size constraint to the unencoded pwd (validation step on the domain life cycle), wich will pass because the pwd typed by the user is in that range. 验证过程会将大小约束应用于未编码的pwd(域生命周期中的验证步骤),由于用户键入的pwd在该范围内,因此将通过。 but on the save() method (persistance step on the domain life cycle) the pwd will be encoded before an insert or update. 但是在save()方法(域生命周期中的持久性步骤)上,pwd将在插入或更新之前进行编码。 The enconding method will create a pwd with a size bigger than your constraint and Hibernate will fail the assert() for the pwd size. enconding方法将创建一个大小大于您的约束的pwd,并且Hibernate将使pwd大小的assert()失败。

Solution: 解:

Use the minSize constraint if you don't need to worry about the maxSize 如果您不必担心maxSize,请使用minSize约束

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

If you need to validate the maxSize, then I recommend you do the validation on your Service or Controller layer before creating the domain instance. 如果需要验证maxSize,则建议您在创建域实例之前在Service或Controller层上进行验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM