2012-08-31 12 views
9

¿Existe alguna manera de definir una regla de validación de Hibernate usando las anotaciones definidas como here, estableciendo que al menos un campo no será nulo?Anotación de validación de hibernación: valide que al menos un campo no sea nulo

Esto sería un ejemplo hipotético (@OneFieldMustBeNotNullConstraint no existe realmente):

@Entity 
@OneFieldMustBeNotNullConstraint(list={fieldA,fieldB}) 
public class Card { 

    @Id 
    @GeneratedValue 
    private Integer card_id; 

    @Column(nullable = true) 
    private Long fieldA; 

    @Column(nullable = true) 
    private Long fieldB; 

} 

En el caso ilustrado, FieldA puede ser nulo o FIELDB puede ser nulo, pero no ambos.

Una forma sería crear mi propio validador, pero me gustaría evitarlo si ya existe. Por favor, comparta un validador si ya tiene uno ... ¡gracias!

Respuesta

13

finalmente escribió todo el validador:

import static java.lang.annotation.ElementType.TYPE; 
import static java.lang.annotation.RetentionPolicy.RUNTIME; 

import java.lang.annotation.Documented; 
import java.lang.annotation.Retention; 
import java.lang.annotation.Target; 

import javax.validation.Constraint; 
import javax.validation.ConstraintValidator; 
import javax.validation.ConstraintValidatorContext; 
import javax.validation.Payload; 

import org.apache.commons.beanutils.PropertyUtils; 

@Target({ TYPE }) 
@Retention(RUNTIME) 
@Constraint(validatedBy = CheckAtLeastOneNotNull.CheckAtLeastOneNotNullValidator.class) 
@Documented 
public @interface CheckAtLeastOneNotNull { 

    String message() default "{com.xxx.constraints.checkatleastnotnull}"; 

     Class<?>[] groups() default {}; 

     Class<? extends Payload>[] payload() default {}; 

     String[] fieldNames(); 

     public static class CheckAtLeastOneNotNullValidator implements ConstraintValidator<CheckAtLeastOneNotNull, Object> { 

      private String[] fieldNames; 

      public void initialize(CheckAtLeastOneNotNull constraintAnnotation) { 
       this.fieldNames = constraintAnnotation.fieldNames(); 
      } 

      public boolean isValid(Object object, ConstraintValidatorContext constraintContext) { 


       if (object == null) 
        return true; 

       try { 

        for (String fieldName:fieldNames){ 
         Object property = PropertyUtils.getProperty(object, fieldName); 

         if (property!=null) return true; 
        } 

        return false; 

       } catch (Exception e) { 
        System.printStackTrace(e); 
        return false; 
       } 
      } 

     } 

} 

Ejemplo de uso:

@Entity 
@CheckAtLeastOneNotNull(fieldNames={"fieldA","fieldB"}) 
public class Reward { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    private Integer fieldA; 
    private Integer fieldB; 

    [...] // accessors, other fields, etc. 
} 
3

Simplemente escriba su propio validador. No debería ser muy simple: iterar sobre los nombres de campo y obtener valores de campo mediante el uso de la reflexión.

Concepto:

Collection<String> values = Arrays.asList(
    BeanUtils.getProperty(obj, fieldA), 
    BeanUtils.getProperty(obj, fieldB), 
); 

return CollectionUtils.exists(values, PredicateUtils.notNullPredicate()); 

Hay que utilizan métodos de commons-beanutils y commons-collections.

+0

Gracias, eso me ayudó a escribir la parte introspección usando PropertyUtils.getProperty. – Resh32

Cuestiones relacionadas