Grails中g:form提交数据库时字段值为null的问题排查
兄弟,太懂这种跟着教程一步步走,结果卡在莫名其妙地方的憋屈了!你说执行save()时进了else分支、字段全是null,大概率是数据绑定没生效,给你列几个最常见的排查点,一个个核对:
表单字段
name必须和Domain类属性完全匹配
Groovy是大小写敏感的,比如你的Domain类里定义的是String userEmail,那表单输入框的name属性必须一模一样是userEmail,不能写成useremail或者email这种变体。Grails靠name字段来匹配Domain属性,名字对不上自然绑定不上数据,结果就是null。
正确的g:field写法示例:<g:field name="userEmail" value="${instance?.userEmail}" />用普通input标签的话也得保证
name一致:<input type="text" name="userEmail" value="${instance?.userEmail}" />检查
g:form的controller和action是否正确
确保你的表单指向了正确的控制器和save方法,比如你的控制器类是UserController,那g:form的写法应该是:<g:form controller="user" action="save"> <!-- 表单内容 --> </g:form>要是controller名字写错(比如写成
User而不是小写的user)、action写成saveUser而非save,请求可能根本没走到你写的save方法,参数自然传不过去。Domain类属性不能设为private
Grails的数据绑定机制需要访问Domain的属性,所以属性不能加private修饰符,正确的Domain定义应该是:class User { String username String email // 不需要加private,用Groovy默认访问权限即可 }要是写成
private String username,绑定机制没法读取赋值,结果就是null。检查数据绑定的白名单配置
Grails为了安全,默认会限制批量赋值的字段。如果你的save方法用了bindData或者直接new User(params),得明确指定允许绑定的字段:def save() { def user = new User() // 明确列出允许绑定的字段,避免被安全机制过滤 bindData(user, params, [include: ['username', 'email']]) if(user.save(flush: true)) { redirect action: 'index' } else { render view: 'create', model: [user: user] } }要是没指定允许的字段或者漏了目标字段,这些字段就会被过滤掉,变成null。
排查是否用了普通HTML form而非g:form(概率低但可检查)
要是你用了普通的<form>标签而不是Grails的<g:form>,可能会因为缺少CSRF令牌导致请求异常,但这种情况一般会返回403错误,不过如果你的项目跳过了CSRF校验,也可能出现参数丢失的情况,优先还是看前面几个核心点。
你可以先从第一个点开始排查,这是最容易踩的坑!要是还是解决不了,可以把你的Domain类、GSP表单代码和save方法代码贴出来,我再帮你细查~
内容的提问来源于stack exchange,提问作者Jack_Russell

