如何从"发生异常后不刷新会话"错误中恢复?

Ant*_*t's 5 grails groovy hibernate exception

我有两节课:

用户

class User {
    //relationships. . . .
    static belongsTo = [ company : Company, role : Role ]
    static hasMany = [ holidays : Holiday ]
    String login
    String password
        static constraints = {
        login(unique:true,size:6..15)
        }
    String toString() {
        this.login
    }
}
Run Code Online (Sandbox Code Playgroud)

而另一个类是这样的:

作用:

class Role {
    String roleName
    String privilege
    static hasMany = [ user : User ]
        static constraints = {  
        privilege(nullable:true)
        roleName(unique:true)
        }
    String toString() {
        this.roleName
    }
}
Run Code Online (Sandbox Code Playgroud)

我写了一个像这样的集成测试:

            def user1 = new User(login:"aravinth", password:"secret")
            def user2 = new User(login:"anto", password:"secret")
            def user3 = new User(login:"antoa", password:"secret")
            def role1 = new Role(roleName:"manager").save()
            def role2 = new Role(roleName:"devleoper").save()
            role1.addToUser(user1)      
            role1.addToUser(user2)      
            role2.addToUser(user3)  
            assert "manager" == user1.role.roleName
Run Code Online (Sandbox Code Playgroud)

此测试工作正常.但是当我将以下行添加到上面的测试代码中时:

def roleMembers = Role.findByRoleName("manager")
Run Code Online (Sandbox Code Playgroud)

我收到这样的错误:

null id in mnm.schedule.User entry (don't flush the Session after an exception occurs)
org.hibernate.AssertionFailure: null id in mnm.schedule.User entry (don't flush the Session after an exception occurs)
    at org.grails.datastore.gorm.GormStaticApi.methodMissing(GormStaticApi.groovy:108)
    at mnm.schedule.RoleItntegrationTests.testAddingRolesToUser(RoleItntegrationTests.groovy:44)
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?我哪里错了?

我正在使用Grails 2.0.

提前致谢.

Anu*_*ora 10

您收到此错误的原因是,当执行语句Role.findBy静态方法时,Hibernate(由Grails GORM使用)检查是否需要"autoFlush".由于存在新的临时Role对象,Hibernate会尝试自动刷新会话.但是,此时存在尚未与角色关联的新用户对象(在用户域中不可为空).因此,在刷新时,用户对象不会通过验证,因此具有异常中提到的空id.

解决此问题的方法是在开始创建/更新相同类型的实体之前进行所有数据库读取调用(例如findBy方法).

另一个选项(虽然不是很好)是设置会话刷新模式手册.

    User.withSession{ sessionObj ->
        sessionObj.setFlushMode(FlushMode.MANUAL);
        //put your Role.findBy mthod call here
        sessionObj.setFlushMode(FlushMode.AUTO);

    }
Run Code Online (Sandbox Code Playgroud)