Grails 如何知道验证错误的原因
如果由于某种原因保存失败,下面的代码将抛出grails.validation.ValidationException。但结果是一个普遍的错误。如何知道错误的实际原因,以便向用户报告Grails 如何知道验证错误的原因,grails,grails-validation,Grails,Grails Validation,如果由于某种原因保存失败,下面的代码将抛出grails.validation.ValidationException。但结果是一个普遍的错误。如何知道错误的实际原因,以便向用户报告 def addChild(cName,Parent theParent) { println "add child: ${cName}" def theChild = new Child(name:cName,parent:theParent) theChild.save(failOnErr
def addChild(cName,Parent theParent) {
println "add child: ${cName}"
def theChild = new Child(name:cName,parent:theParent)
theChild.save(failOnError:true)
return theChild
}
这是返回的堆栈跟踪。我碰巧知道这是由于违反了唯一的约束而导致的,因为我是故意造成的,但跟踪中没有任何东西表明这是原因,而不是其他约束违反
org.codehaus.groovy.runtime.InvokerInvocationException: grails.validation.ValidationException: Validation Error(s) Occurred During Save
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:619)
Caused by: grails.validation.ValidationException: Validation Error(s) Occurred During Save
at AddRecordsService.addChild(AddRecordsService.groovy:30)
at AddRecordsService$addChild.callCurrent(Unknown Source)
at AddRecordsService.addAll(AddRecordsService.groovy:11)
at AddRecordsService$$FastClassByCGLIB$$e47d68f4.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at AddRecordsService$$EnhancerByCGLIB$$cdfdcc61.addAll(<generated>)
at AddRecordsService$addAll.call(Unknown Source)
at AddrecordController$_closure2.doCall(AddrecordController.groovy:14)
at AddrecordController$_closure2.doCall(AddrecordController.groovy)
... 32 more
我认为ValidationException引用了验证失败的对象?如果是,则检查errors属性以获取错误列表 如果没有,您将需要捕获它,然后检查child.errors以查找错误。当然,save(failOnError:true)方法目前提供的有关是什么验证导致了问题的信息太少。(您真的想要解析控制器中的异常消息吗?)但是,您可以考虑多个替代方案来处理两个不同的问题,事务回滚和通信验证错误信息。 一种替代方法是完全避免数据的持久性。首先,调用child.validate()以查看是否可以保存该孩子。如果没有验证失败,validate()将返回true,因此调用child.save()。如果发生验证错误,它们将记录在孩子的errors对象中。然后,可以检查返回给调用控制器的新创建的子级是否存在错误,或者只在视图中向用户显示 另一种选择是不使用声明性事务;i、 e.在服务上设置static transactional=false。然后,您的代码可以管理事务本身;大概是这样的:
Child.withTransaction { txStatus ->
try {
child.save(failOnError:true)
} catch (ValidationException e) {
// rollback, but swallow exception, requiring caller to check child for errors
txStatus.setRollbackOnly()
}
}
最后,您的问题意味着您希望控制器处理错误信息,例如呈现原始页面,以便用户可以更正条目。由于child是经过验证的,因此在抛出异常(您自己的或ValidationException)时,返回child将不起作用。但是,在save()调用期间,该子级将填充错误。代替传递字符串和父级,然后实例化服务中的子代,您应该考虑实例化调用方中的子并通过引用传递它。然后,当save()失败时,即使保存(failOnError:true)导致ValidationException,也会填充子项的错误。调用方可以捕获ValidationException,然后将子项作为视图模型的一部分传递回
就个人而言,我认为第一种选择(先调用validate())或最后一种选择(在服务外部实例化子项)比手动管理事务更可取。在Grails中,声明性事务管理对于整个服务来说要么全有,要么全无。也就是说,如果您为服务设置了static transactional=false,则必须手动管理服务的每个方法中的所有事务。KISS原则应该在这里应用。老问题,但如果有人偶然发现它:在服务中,Grails(2.1)习惯用法是调用save(),如果save失败,则抛出ValidationException
if (!theChild.save()) {
throw new ValidationException(theChild.errors)
}
通常不调用save(failOnError:true)
。相反,在控制器中,您捕获ValidationException:
try {
service.addChild(child)
} catch (ValidationException e) {
errors.allErrors.each {
// do something with each error code
}
}
同样的想法,如果你在你的控制器中做所有的工作。在这种情况下,您不需要抛出然后捕获异常。当然,您可以当场处理
子错误。尝试使用grails命令类进行验证
示例:
class ParentCommand {
.....field.....
........constraint.....
}
def addChild(cName,ParentCommand cmd) {
if(cmd.hasErrors()) {
render (cmd.errors as JSON).toString();
return "false";
}
您收到了什么样的错误消息?谢谢您的回复。这让我做了更好的搜索。看起来这将在1.2RC1中解决
class ParentCommand {
.....field.....
........constraint.....
}
def addChild(cName,ParentCommand cmd) {
if(cmd.hasErrors()) {
render (cmd.errors as JSON).toString();
return "false";
}