5

@LengthIfNotBlank(min=,max=)Hibernates 制約に基づいてカスタム制約を作成したいと思い@Lengthます。

@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = LengthIfNotBlankValidator.class)
@Documented
public @interface LengthIfNotBlank {
    String message() default "{com.mycompany.LengthIfNotBlank}";
    Class<? extends Payload>[] payload() default {};
    int max() default Integer.MAX_VALUE;
    Class<?>[] groups() default {};
    int min() default 0;
}

public class LengthIfNotBlankValidator extends LengthValidator {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        return StringUtils.isBlank(value) || super.isValid(value, constraintValidatorContext);
    }
}

例外:

[java] javax.validation.ValidationException: Unable to initialize com.example.constraints.LengthIfNotBlankValidator
[java] Caused by: java.lang.ClassCastException: $Proxy32 cannot be cast to org.hibernate.validator.constraints.Length

アップデート

まだこの例外が発生しています:-(

public class LengthIfNotBlankValidator extends LengthValidator {
    public void initialize(LengthIfNotBlank parameters) {
        Map<String,Object> elements = new HashMap<String,Object>();
        elements.put("message", parameters.message());
        elements.put("payload", parameters.payload());
        elements.put("groups", parameters.groups());
        elements.put("min", parameters.min());
        elements.put("max", parameters.max());

        AnnotationDescriptor<Length> descriptor = AnnotationDescriptor.getInstance(Length.class, elements);
        Length length = AnnotationFactory.create(descriptor);
        super.initialize(length);
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        return StringUtils.isBlank(value) || super.isValid(value, constraintValidatorContext);
    }
}
4

2 に答える 2

2

注釈型は継承できないため、型の実際のインスタンスをオーバーライドしinitialize()て に渡す必要があります。Lengthsuper.initialize()

注釈型のインスタンスを直接作成することはできないため、 のようなものを使用する必要があることに注意してくださいAnnotationFactory

また、型の安全性の制約により、コンパイラがそれを許可するかどうかもわかりません。そうでない場合は、継承の代わりに構成を使用します (つまり、 type のフィールドを作成しますLengthValidator)。

于 2012-07-09T07:52:51.057 に答える
1

私はあなたがそれを気にするべきではないと思います.HibernateLengthValidatorは本当にシンプルで、あなたが何をしても、次のように自分でコードを再実装した場合より多くのコードになります:

public class LengthIfNotBlankValidator implements ConstraintValidator<LengthIfNotBlank, String> {
    private int min;
    private int max;

    public void initialize(LengthIfNotBlank parameters) {
        min = parameters.min();
        max = parameters.max();
        validateParameters();
    }

    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        if ( StringUtils.isBlank(value) ) {
            return true;
        }
        int length = value.length();
        return length >= min && length <= max;
    }

    private void validateParameters() {
        if ( min < 0 ) {
            throw new IllegalArgumentException( "The min parameter cannot be negative." );
        }
        if ( max < 0 ) {
            throw new IllegalArgumentException( "The max parameter cannot be negative." );
        }
        if ( max < min ) {
            throw new IllegalArgumentException( "The max cannot be less than the min." );
        }
    }
}

(これは、特定のケースに合わせて調整された Hibernate のコードです)。

また、バリデーターに必須のLengthValidator実装中に拡張することはできないと思います。ConstraintValidator<LengthIfNotBlank, String>

ただし、パラメーター化されていないバリデーター (または定数パラメーターを持つバリデーター) を再利用したい場合は、再利用されたバリデーターでアノテーションを付けるだけでよいことに注意してください (おそらく追加することもできます@ReportAsSingleViolation) 。

于 2012-07-09T08:54:40.543 に答える