如何在枚举中使用Hibernate验证注释?

mem*_*und 12 java annotations hibernate

如何使用hibernate注释来验证枚举成员字段?以下不起作用:

enum UserRole {
   USER, ADMIN;
}

class User {
   @NotBlank //HV000030: No validator could be found for type: UserRole.
   UserRole userRole;
}
Run Code Online (Sandbox Code Playgroud)

Seb*_*ber 37

注意,您还可以创建一个验证器来检查String是枚举的一部分.

public enum UserType { PERSON, COMPANY }

@NotNull
@StringEnumeration(enumClass = UserCivility.class)
private String title;
Run Code Online (Sandbox Code Playgroud)
@Documented
@Constraint(validatedBy = StringEnumerationValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, PARAMETER, CONSTRUCTOR })
@Retention(RUNTIME)
public @interface StringEnumeration {

  String message() default "{com.xxx.bean.validation.constraints.StringEnumeration.message}";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};

  Class<? extends Enum<?>> enumClass();

}
Run Code Online (Sandbox Code Playgroud)
public class StringEnumerationValidator implements ConstraintValidator<StringEnumeration, String> {

  private Set<String> AVAILABLE_ENUM_NAMES;

  @Override
  public void initialize(StringEnumeration stringEnumeration) {
    Class<? extends Enum<?>> enumSelected = stringEnumeration.enumClass();
    //Set<? extends Enum<?>> enumInstances = EnumSet.allOf(enumSelected);
    Set<? extends Enum<?>> enumInstances = Sets.newHashSet(enumSelected.getEnumConstants());
    AVAILABLE_ENUM_NAMES = FluentIterable
            .from(enumInstances)
            .transform(PrimitiveGuavaFunctions.ENUM_TO_NAME)
            .toSet();
  }

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    if ( value == null ) {
      return true;
    } else {
      return AVAILABLE_ENUM_NAMES.contains(value);
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

这很好,因为你没有丢失"错误值"的信息.你可以得到一条消息

值"someBadUserType"不是有效的UserType.有效的UserType值为:PERSON,COMPANY


编辑

对于那些想要非番石榴版本的人来说,它应该适用于:

public class StringEnumerationValidator implements ConstraintValidator<StringEnumeration, String> {

  private Set<String> AVAILABLE_ENUM_NAMES;

  public static Set<String> getNamesSet(Class<? extends Enum<?>> e) {
     Enum<?>[] enums = e.getEnumConstants();
     String[] names = new String[enums.length];
     for (int i = 0; i < enums.length; i++) {
         names[i] = enums[i].name();
     }
     Set<String> mySet = new HashSet<String>(Arrays.asList(names));
     return mySet;
  }

  @Override
  public void initialize(StringEnumeration stringEnumeration) {
    Class<? extends Enum<?>> enumSelected = stringEnumeration.enumClass();
    AVAILABLE_ENUM_NAMES = getNamesSet(enumSelected);
  }

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    if ( value == null ) {
      return true;
    } else {
      return AVAILABLE_ENUM_NAMES.contains(value);
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

要自定义错误消息并显示相应的值,请查看:https://stackoverflow.com/a/19833921/82609


Sur*_*tta 10

@NotBlank

验证带注释的字符串不为null或为空.与NotEmpty的区别在于尾随空格被忽略.

其中UserRole不是字符串和object 使用@NotNull

带注释的元素不能为null.接受任何类型.


Raf*_*Raf 6

我想与上面塞巴斯蒂安的答案更密切相关,代码行更少,并且EnumSet.allOfrawtypes警告为代价使用

枚举设置

public enum FuelTypeEnum {DIESEL, PETROL, ELECTRIC, HYBRID, ...}; 
public enum BodyTypeEnum {VAN, COUPE, MUV, JEEP, ...}; 
Run Code Online (Sandbox Code Playgroud)

注释设置

@Target(ElementType.FIELD) //METHOD, CONSTRUCTOR, etc.
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValidator.class)
public @interface ValidateEnum {
    String message() default "{com.xxx.yyy.ValidateEnum.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    Class<? extends Enum<?>> targetClassType();
}
Run Code Online (Sandbox Code Playgroud)

验证器设置

public class EnumValidator implements ConstraintValidator<ValidateEnum, String> {
    private Set<String> allowedValues;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void initialize(ValidateEnum targetEnum) {
        Class<? extends Enum> enumSelected = targetEnum.targetClassType();
        allowedValues = (Set<String>) EnumSet.allOf(enumSelected).stream().map(e -> ((Enum<? extends Enum<?>>) e).name())
                .collect(Collectors.toSet());
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value == null || allowedValues.contains(value)? true : false; 
    }
} 
Run Code Online (Sandbox Code Playgroud)

现在继续注释您的字段如下

@ValidateEnum(targetClassType = FuelTypeEnum.class, message = "Please select ...." 
private String fuelType; 

@ValidateEnum(targetClassType = BodyTypeEnum.class, message = "Please select ...." 
private String bodyType; 
Run Code Online (Sandbox Code Playgroud)

以上假设您已Hibernate Validator设置并使用默认注释。