赞
踩
在事务中,发现无法捕获 ConstraintViolationException 异常,折腾了很久,最终解决了,怪自己当初异常那部分没好好看。
背景如下
我的需求是,当用户修改资料的时候,字段长度不合法的时候,会给以提示。前端是使用 bootstrapValidator 提示,当用户绕过 bootstrapValidator 限制,我们依然可以通过后端来限制。比如 Hibernate (或者 Spring Data JPA) 的验证注解 @NotEmpty,@Size 等来帮我们验证,如果验证不通过会抛一个 ConstraintViolationException 异常,我们可以格式化该异常的信息,然后返回给前台。
User 实体
Controller
其中 ConstraintViolationExceptionHandler 类是自己写的,用来格式化异常信息
Service
当修改资料,将昵称改成一个字(上面 User 实体里有限制昵称至少2个字符)
然后发现,并没有捕获到 ConstraintViolationException 异常,而是捕获到了 TransactionSystemException 异常,异常信息如下
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
显然,这不是我们想要的
原因:ConstraintViolationException 异常是包裹在 TransactionSystemException 里的,我们如果直接捕获它,可能永远都捕获不到。
所以我们应该先捕获 TransactionSystemException 而不是 ConstraintViolationException,然后去找它的 getCause(),一层一层地找,直到找到 ConstraintViolationException,我们就可以做事了,无论是中断还是返回。
通过 Debug 我们发现 ConstraintViolationException 被 RollbackException 包裹,RollbackException 又被 TransactionSystemException 包裹,我们只需要捕获 TransactionSystemException 异常,然后通过getCause() 方法来找我们需要的异常就行了。
所以应该调用直到遇到违反约束的 getCause()
方法 Exception。
最终的解决方案就是,改写 Controller 里的捕获异常的部分
现在就能进入 t instanceof ConstraintViolationException 里了,前台效果图如下
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。