2011-12-26 42 views
5

我有两个类:如何恢复`发生异常后不刷新会话'错误?

用户

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

并有另一个类是这样的:

角色

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

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

  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 

此测试正常工作。但是,当我这下面一行添加到我上面的测试代码:

def roleMembers = Role.findByRoleName("manager") 

我得到这样的错误:

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) 

回事请告诉我?我哪里错了?

我使用的是Grails 2.0。

在此先感谢。

回答

10

你得到这个错误的原因是当执行语句Role.findBy静态方法时,Hibernate(由grails GORM使用)检查是否需要“autoFlush”。由于存在新的临时角色对象,因此Hibernate会尝试自动刷新会话。但是,在这一点上,新的用户对象存在,这些对象尚未与角色关联(在用户域中不能为空)。因此,在刷新时,用户对象不会通过验证,因此具有如例外中所述的空id。

解决此问题的方法是在启动创建/更新相同类型的实体之前,使所有DB读取调用(例如findBy方法)

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

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

    } 
0

如果你正在使用Spring Security的核心,如果添加约束size或者创建自定义validator来检查,如果“密码”等于“确认密码”发生同样的错误。解决方法是在这些情况下使用命令对象。这个案例解决here

一般来说,如果某些字段为空,但它不应该为空,而是通过约束(通常是因为代码中有一些错误),则可能发生此错误。该数据库具有非空规则,因此不会创建该条目。那么Grails将显示那个丑陋的错误。

相关问题