SpringコマンドBeanのJava.lang.Double
フィールドの最大値と最小値(値は指定された値の範囲内にある必要があります)を検証する方法を探しています。
public final class WeightBean
{
@Max(groups={ValidationGroup.class}, value=Double.MAX_VALUE, message="some key or default message")
@Min(groups={ValidationGroup.class}, value=1D, message="some key or default message")
private Double txtWeight; //Getter and setter.
public interface ValidationGroup{}
}
ただし、 @Max
と @Min
はどちらもJava.lang.Double
値をとることはできません。
丸め誤差のため、doubleとfloatはサポートされていないことに注意してください(一部のプロバイダーはおおよそのサポートを提供する場合があります)
では、そのようなフィールドを検証する方法は何ですか?
Spring3.2.0とHibernateValidator 4.3.1CR1を使用しています。
アノテーションを使用することはできますが、場合によっては誤った結果が得られる可能性があります。これはdoublesの一般的な問題であり、多くの場合_Double_sは避ける必要があります。たぶん、別のタイプに切り替えることが最善の解決策ですか? BigDecimalたとえば?
BigDecimal(またはBigInteger)に切り替えた場合は、 @ DecimalMin または @ DecimalMax を使用できます。しかし、これはまだfloatまたはdoubleの解決策ではありません。
double
型とfloat
型を回避し、精度とスケールに基づいてBigDecimal
値を検証できるカスタムバリデーターを実装しました。
制約記述子。
package constraintdescriptor;
import constraintvalidator.BigDecimalRangeValidator;
import Java.lang.annotation.Documented;
import static Java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static Java.lang.annotation.ElementType.FIELD;
import static Java.lang.annotation.ElementType.METHOD;
import Java.lang.annotation.Retention;
import static Java.lang.annotation.RetentionPolicy.RUNTIME;
import Java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = BigDecimalRangeValidator.class)
@Documented
public @interface BigDecimalRange {
public String message() default "{Java.math.BigDecimal.range.error}";
public Class<?>[] groups() default {};
public Class<? extends Payload>[] payload() default {};
long minPrecision() default Long.MIN_VALUE;
long maxPrecision() default Long.MAX_VALUE;
int scale() default 0;
}
制約バリデーター。
package constraintvalidator;
import constraintdescriptor.BigDecimalRange;
import Java.math.BigDecimal;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public final class BigDecimalRangeValidator implements ConstraintValidator<BigDecimalRange, Object> {
private long maxPrecision;
private long minPrecision;
private int scale;
@Override
public void initialize(final BigDecimalRange bigDecimalRange) {
maxPrecision = bigDecimalRange.maxPrecision();
minPrecision = bigDecimalRange.minPrecision();
scale = bigDecimalRange.scale();
}
@Override
public boolean isValid(final Object object, final ConstraintValidatorContext cvc) {
boolean isValid = false;
if (object == null) { // This should be validated by the not null validator (@NotNull).
isValid = true;
} else if (object instanceof BigDecimal) {
BigDecimal bigDecimal = new BigDecimal(object.toString());
int actualPrecision = bigDecimal.precision();
int actualScale = bigDecimal.scale();
isValid = actualPrecision >= minPrecision && actualPrecision <= maxPrecision && actualScale <= scale;
if (!isValid) {
cvc.disableDefaultConstraintViolation();
cvc.buildConstraintViolationWithTemplate("Precision expected (minimun : " + minPrecision + ", maximum : " + maxPrecision + "). Maximum scale expected : " + scale + ". Found precision : " + actualPrecision + ", scale : " + actualScale).addConstraintViolation();
}
}
return isValid;
}
}
これは、必要に応じて、他のタイプにも拡張できます。
そして最後にBeanで、型BigDecimal
のプロパティに@BigDecimalRange
アノテーションは次のとおりです。
package validatorbeans;
public final class WeightBean {
@BigDecimalRange(minPrecision = 1, maxPrecision = 33, scale = 2, groups = {ValidationGroup.class}, message = "The precision and the scale should be less than or equal to 35 and 2 respectively.")
private BigDecimal txtWeight; // Getter and setter.
public interface ValidationGroup {}
}
@AssertTrue
の@AssertFalse
/javax.validation.constraints
と組み合わせて使用すると便利な場合があります
public final class WeightBean {
@NotNull
private Double txtWeight; //Getter and setter.
@AssertTrue
public boolean getTxtWeightCheck() {
return txtWeight > 0.1 && txtWeight < 0.9;
}
}
HibernateバリデータAPIから@Digits
を使用することもできます
@Digits(integer = 10 /*precision*/, fraction = 2 /*scale*/)
Hibernate Validatorの新しいバージョン(少なくとも6.0.17)は、doubleで@DecimalMin/Max
アノテーションをサポートします
検証用のクラス を参照してください