[Grails] 是Grails预先抓取的重大bug?!

zengsun 2008-01-08
在Grails中雇员和角色的多对多关系中,我用了预先抓取角色对象。
代码如下:
class Employee {
    String name
    String login
    String password
    Boolean loginEnable
    String identification
    Date birthday
    Date joinDate
    String tel

    static belongsTo = Role
    
    static hasMany = [events:Event, roles:Role]

    static fetchMode = [roles: "eager"]

    static constraints = {
        name(size:2..20)
        login(size:2..20, unique:true, nullable:false)
        password(size:6..12)
        loginEnable()
        identification(maxSize:18)
        birthday(max:new Date() - 18*365)
        joinDate()
        tel(nullable:true)
    }

    String toString() {
        this.name
    }
}

class Role {
    String title

    static hasMany = [employees:Employee]

    String toString() {
        this.title
    }
}

可是,这时如果有雇员兼有多个角色时,Employee.list()返回的雇员列表的对象竟然出现多个重复雇员对象(就因为该雇员兼有多个角色)!!!

我现在对Grails开发团队的技术实力产生怀疑!

究竟这个团队是否可以为用户提供一个稳定健壮、安全、强大的开发框架?!(学习django框架时,从来没有遇到如此低级的错误!)

建议大家对使用Grails框架持谨慎态度!!!

 

agile_boy 2008-01-08
这个我在处理Hibernate的时候也碰到过,得需要特别的trick才能绕过
agile_boy 2008-01-08
new Role(title:'kkl').addToEmployees(new Employee(name:'kk',login:'kkkl')).addToEmployees(new Employee(name:'kk1',login:'kkkl1')).save()
new Role(title:'kk2').addToEmployees(new Employee(name:'kk2',login:'kkk2')).save()
Employee.list()

以上代码在grails console 下运行没有问题,没有看到你所说的重复问题,可否将你的用法share一下呢?
zengsun 2008-01-08
agile_boy 写道
new Role(title:'kkl').addToEmployees(new Employee(name:'kk',login:'kkkl')).addToEmployees(new Employee(name:'kk1',login:'kkkl1')).save()
new Role(title:'kk2').addToEmployees(new Employee(name:'kk2',login:'kkk2')).save()
Employee.list()

以上代码在grails console 下运行没有问题,没有看到你所说的重复问题,可否将你的用法share一下呢?

用法和你的相差不大。我在update时,加了一行代码。参数roles是角色对象的id数组:

def update = {
        def employee = Employee.get( params.id )
        if(employee) {
            employee.properties = params
            params.roles.each { employee.addToRoles(Role.get(it)) }
            if(!employee.hasErrors() && employee.save()) {
                flash.message = "Employee ${params.id} updated"
                redirect(action:show,id:employee.id)
            }
            else {
                render(view:'edit',model:[employee:employee])
            }
        }
        else {
            flash.message = "Employee not found with id ${params.id}"
            redirect(action:edit,id:params.id)
        }
    }
 
agile_boy 2008-01-09
我觉得可能是你的用法有点问题,GORM的文档上有明确说明,在many-to-many的关系中,只有对管理者操作才会引起级联动作,此处你的管理者应该是Role。
zengsun 2008-01-09
agile_boy 写道
我觉得可能是你的用法有点问题,GORM的文档上有明确说明,只有many-to-many的关系中,只有对管理者操作才会引起级联动作,此处你的管理者应该是Role。

了解你的说法。
但文档上说的是全是新对象的情况下!反向的话,新对象无法保存到数据库中!
我没有考虑到角色对象已经存在,员工要添加新的角色非要在角色中加员工的做法(就算是这样也比较别扭)。
谢谢!
zengsun 2008-01-14
zengsun 写道
agile_boy 写道
我觉得可能是你的用法有点问题,GORM的文档上有明确说明,只有many-to-many的关系中,只有对管理者操作才会引起级联动作,此处你的管理者应该是Role。

了解你的说法。
但文档上说的是全是新对象的情况下!反向的话,新对象无法保存到数据库中!
我没有考虑到角色对象已经存在,员工要添加新的角色非要在角色中加员工的做法(就算是这样也比较别扭)。
谢谢!

修改代码为:
params.roles.each { Role.get(it).addToEmployees(employee) }

但错误依旧!!!
geszJava 2008-01-16
呃?many-to-many没怎么用过,这种错误也不算什么低级错误?顶多算个bug吧.
jy00057800 2008-01-23
大家可以看看 我这个多对多 的代码 可以吗 ,可以用但是 ,感觉代码有些冗余
   def save={
        def role = new Role()
        bindData(role,params)
        //删除页面 接受的用户,菜单的数据
        role.users?.toList().each {
            role.users.remove(it)
        }
        role.menus?.toList().each {
            role.menus.remove(it)
        }
        //添加用户,权限菜单      
        request.getParameterValues("users")?.each {t->
             role.addToUsers(User.get(  t  )  )
        }
        request.getParameterValues("menus")?.each {t->
             role.addToMenus(Menu.get(  t  )  )
        }
        role.save()
        redirect(action:list)      
    }
下面是更新
def update={
         def role = Role.get(params.id)
         //删除数据库中的role关联数据
        role.users?.toList().each {
            role.removeFromUsers(it)
        }
        role.menus?.toList().each {
            role.removeFromMenus(it)
        }
        //绑定页面接受的数据
         bindData(role,params)        
        //删除页面 接受的用户,菜单的数据
        role.users?.toList().each {
            role.users.remove(it)
        }
        role.menus?.toList().each {
            role.menus.remove(it)
        }

        //添加用户,菜单到数据库关联对象中
         request.getParameterValues("users")?.each {t->
             role.addToUsers(User.get(  t  )  )
        }              
        request.getParameterValues("menus")?.each {        
           role.addToMenus(Menu.get(  it  )  )
        }        
        role.save()
        redirect(action:list)
    }
jy00057800 2008-01-23
我发现 bindData(role,params)后 页面的 一些value 和 domain的 Set绑定一起去了 ,所以我先把页面绑定进去的删除在到数据库里面添加
Global site tag (gtag.js) - Google Analytics