7

Sto cercando un modo per convalidare un campo java.lang.Double nel bean di comando Spring per i suoi valori massimo e minimo (un valore deve essere compreso tra un determinato intervallo di valori) come ,Validazione di valori double e float tramite Hibernate Validator - validazione bean

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{}   
} 

Ma sia @Max e @Min non può assumere un valore java.lang.Double.

noti che doppio e galleggiante non sono supportati a causa di errori di arrotondamento (alcuni provider potrebbe fornire qualche supporto approssimativa)

Allora, qual è il modo di convalidare tali campi?

Sto lavorando con Spring 3.2.0 e Hibernate Validator 4.3.1 CR1.

+0

Se vuoi posso implementare un DoubleRangeValidator nella mia collezione di vincoli qui: http://waxolunist.github.com/validationconstraints/ - Basta aprire un problema, puoi averlo domani su Maven Central. – Christian

+0

@ Waxolunist - Grazie ma non ho capito. – Tiny

risposta

7

È possibile utilizzare l'annotazione, ma si potrebbero ottenere risultati falsi a seconda. Questo è un problema generale con doppio e imo in molti casi _Double_s dovrebbe essere evitato. Forse passare a un altro tipo è la soluzione migliore? BigDecimal per esempio?

+1

Sono passato a un tipo 'BigDecimal' ma l'attributo' value' di '@ Max' e' @ Min' accetta solo un valore 'Long'. Devo controllare, se un valore è compreso tra un intervallo definito. Ad esempio, a partire da 0,1 a 0,9. Non è possibile con la convalida del bean? – Tiny

+4

Per 'BigDecimal' vedi l'annotazione' @ DecimalMin'. –

3

Ho evitato i tipi double e float e ho implementato un validatore personalizzato in grado di convalidare un valore BigDecimal in base alla precisione e alla scala.

Il descrittore del vincolo.

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; 
} 

Il validatore vincolo.

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; 
    } 
} 

Questo potrebbe essere esteso anche per altri tipi, come e quando richiesto.


E infine nel fagiolo, la proprietà del tipo BigDecimal potrebbe essere annotato @BigDecimalRange di annotazione come segue.

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 {} 
} 
4

Se si è passati a BigDecimal (o BigInteger), è possibile utilizzare @DecimalMin o @DecimalMax. Ma questa non è ancora una soluzione per float o double.

0

È inoltre possibile utilizzare @Digits dal Hibernate Validator API così

@Digits(integer = 10 /*precision*/, fraction = 2 /*scale*/)