【问题标题】:Spring JSR 303 Validation access other field value while Edit/AddSpring JSR 303 验证在编辑/添加时访问其他字段值
【发布时间】:2016-10-14 05:07:16
【问题描述】:

我有一个要求,我想使用 Bean 进行更新/添加。现在我有一个验证,因为名称应该是唯一的。

现在在添加过程中,验证部分可以正常工作,因为它正在通过查询数据库检查唯一值。

现在,当我想更新同一条记录时,它正在尝试检查数据库中的唯一约束,但由于记录已经存在而失败。

角色豆

public class Role {
    @NotEmpty
    @Pattern(regexp = "[a-zA-Z ]*")
    @UniqueValue(query = AppConstants.UNIQUE_VALIDATION_DB_QUERY)
    private String roleName;
    private String roleDesc;
    private boolean active;
 private String maskRoleName;

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getRoleDesc() {
        return roleDesc;
    }

    public void setRoleDesc(String roleDesc) {
        this.roleDesc = roleDesc;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }
}

我的自定义注释验证器

public class UniqueValueValidator implements ConstraintValidator<UniqueValue, String> {

    @Autowired
    private ValidationDAO validationDAO;

    private String query;

    public void initialize(UniqueValue uniqueValue) {
        this.query = uniqueValue.query();
    }

    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
            if (!StringUtils.isEmpty(value) && !StringUtils.isEmpty(query)) {
                return validationDAO.isValidUniqueField(query, value);
            }
        return true;
    }

}

现在,当我仅从屏幕更新 RoleDesc 字段时,角色名称将被验证并引发验证错误,因为数据库中存在相同的角色名称。有没有一种方法可以让我从屏幕向我的自定义验证器发送其他变量,说以下是更新屏幕,所以只有在字段从之前的值更改时才验证该字段?

【问题讨论】:

    标签: java validation spring-mvc


    【解决方案1】:

    我通过在 getter 方法上进行注释来解决问题,其中所有必需的字段都通过该方法作为单个映射返回,并且在 validationIMPL 中我检索了所有必需的信息并进行了相应的处理。

     private String roleName;
    
     @UniqueValue(query = AppConstants.UNIQUE_VALIDATION_DB_QUERY)
     public Map<String,String> getUniqueValidator(){
       Map<String,String> validatorMap=new HashMap<String,String>();
    
       validatorMap.put("ACTION",type of action(update/new)):
       validatorMap.put("VALUE",this.roleName):
       return validatorMap;
     }
    
     public String getRoleName() {
            return roleName;
     }
    
     public void setRoleName(String roleName) {
            this.roleName = roleName;
     }
    

    【讨论】:

      【解决方案2】:

      您可能正在寻找的是Groups。您可以将注释修改为:

      @UniqueValue(query = AppConstants.UNIQUE_VALIDATION_DB_QUERY, groups = {CreationGroup.class})
      

      您还需要创建一个CreationGroup 接口。

      然后您需要更新调用 bean 验证的拦截器以使用上下文信息(可能由包装验证发生的方法的另一个注释提供)如下所示:

      if (myMethodIsCreatingANewRecord()) {
          validator.validate(address, Default.class, CreationGroup.class);
      } else {
          validator.validate(address, Default.class);
      }
      

      【讨论】:

      • 但是只有在值改变的情况下,我如何传递验证信息。因为即使在添加/编辑中我也需要验证......但在编辑的情况下,我应该仅在值更改时验证
      • 有没有办法将其他字段值(maskRoleName)与当前字段一起传递...以便我可以检查是否 masroleName=roleName 然后没有验证
      • 假设您有一个主键,可用于在更新时查找实体以检查名称是否已更改。这就是您要与 Role 对象一起传递的信息。然而,对于这个特定的问题,我可能会向数据库列添加一个唯一约束,并让它在违反时导致失败。
      • 感谢您的回复。我不想直到 dao 层并抛出异常。相反,我想在验证层处理它。难道不能处理这种类型的场景吗?如果我们可以在我的唯一验证器中访问其他变量,我认为我们可以传递有关如何验证它的信息。但是不知道能不能那样做??
      • 好吧,正如我在答案中提到的,您应该有足够的信息从您调用验证器的位置获取实体的旧版本并使用它来确定该字段是否已更改。例如,如果您的服务正在调用像 editRole(roleId, roleBean) 这样的方法,当您拦截它时,只需获取 roleId 参数并使用它来加载现有实体以用于比较。
      猜你喜欢
      • 2011-10-23
      • 2018-08-15
      • 2013-11-23
      • 2013-12-27
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      相关资源
      最近更新 更多