2016-06-17 28 views
3

私はこのような実体を持って:あなたはそれは大丈夫だ、BICと研究所、空のIBANを提供することができ、」カスタム検証を行うためにカスタムJPA検証

@Entity 
@Table(name = "transaction_receiver") 
public class TransactionReceiver implements Serializable, Addressable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @NotNull 
    @Column(name = "contact_id", nullable = false) 
    private String contactId; 

    @Column(name = "datev_number") 
    private String datevNumber; 

    @NotNull 
    @Column(name = "receiver", nullable = false) 
    private String receiver; 

    @NotNull 
    @Size(min = 22, max = 34) 
    @Column(name = "iban", length = 34, nullable = false) 
    private String iban; 

    @Size(min = 8, max = 11) 
    @Column(name = "bic", length = 11, nullable = false) 
    private String bic; 

    @NotNull 
    @Column(name = "institute") 
    private String institute; 

    @Column(name = "company") 
    private String company; 

、タスク、しかし、もしあれば。上記のconstraitは保持する必要があります "

私はこれを達成するための最もエレガントな方法を探しています。私は何とか汚いどう思うかが、作業 - -

私の現在のソリューションは、@PrePersistステートメントを使用して注釈を@Validが賢明ではありません

@PrePersist 
    public void checkBankData() { 
     boolean ibanEmpty = iban == null || iban.isEmpty(); 
     boolean ibanValid = !ibanEmpty && iban.length() >= 22 && iban.length() <= 34; 
     boolean bicEmpty = bic == null || bic.isEmpty(); 
     boolean bicValid = !bicEmpty && bic.length() >= 8 && bic.length() <= 11; 
     boolean instituteEmpty = institute == null || institute.isEmpty(); 

     boolean validState = (ibanEmpty && bicEmpty && instituteEmpty) || ibanValid && bicValid; 

     if (!validState) { 
      throw new IllegalStateException(
       String.format(
        "bank data is not empty and %s%s%s%s%s", 
        !ibanValid ? "iban has to be from 22 to 34 chars long" : "", 
        !ibanValid && !bicValid ? "and" : "", 
        !bicValid ? "bic has to be from 8 to 11 chars long" : "", 
        !ibanValid && !bicValid && instituteEmpty ? "and" : "", 
        instituteEmpty ? "institue must not be empty" : "" 
       ) 
      ); 
     } 
    } 

そこから例外をスローします。他のアプローチは、ここで説明したようなカスタムバリデーターを定義することです:http://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-customconstraints.html

しかし、これは本当に私の制約のための過剰なもののように見えます。

他に優雅な方法はありませんか?あなたはそれがより大きいかまたは特定の数よりも小さくなければなりません指定する@sizeアノテーションを使用して試みることができるHibernateバリの@NotEmptyと同等のものを持っていないデフォルトのJPAの検証を回避する

おかげ

答えて

3

Hibernate Validation APIの使用は、それほど複雑ではなく、制約のために素晴らしいソリューションです。 しかし、1つのプロジェクトで行ったように、Hibernate Validatorを使用していくつかのクラスを追加するより簡単な制約を定義することができます。あなたの制約は次のようになります:

@Validate(method = "checkBankData", message = "{BankData.invalid.message}") 
@Entity 
@Table(name = "transaction_receiver") 
public class TransactionReceiver implements Serializable, Addressable { 

これを得るには、@ValidateアノテーションとCustomValidatorクラスを定義する必要があります。

@Target({ ElementType.TYPE, ANNOTATION_TYPE }) 
@Retention(RUNTIME) 
@Constraint(validatedBy = CustomValidator.class) 
@Documented 
/** 
* Annotation to allow custom validation against model classes 
*/ 
public @interface Validate { 

    /** 
    * Validation message 
    */ 
    String message(); 

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

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

    /** 
    * Validation method name 
    */ 
    String method() default ""; 
} 


public class CustomValidator implements ConstraintValidator<Validate, BusinessObject> { 

    private static Log log = LogFactory.getLog(CustomValidator.class); 
    private String validator; 


    @Override 
    public void initialize(Validate constraintAnnotation) { 
    validator = constraintAnnotation.method(); 
    } 

    @Override 
    public boolean isValid(BusinessObject bo, ConstraintValidatorContext constraintContext) { 
    try { 
     return isValidForMethod(bo); 
    } catch (Exception e) { 
     /* Error durante la ejecución de la condición o del validador */ 
     log.error("Error validating "+bo, e); 
     return false; 
    } 
    } 


    private boolean isValidForMethod(BusinessObject bo) throws Exception { 
    Method validatorMethod = ReflectionUtils.findMethod(bo.getClass(), validator, new Class[] {}); 
    if (validatorMethod != null) { 
     /* Validator call */ 
     Boolean valid = (Boolean) validatorMethod.invoke(bo); 
     return valid != null && valid; 
    } else { 
     /* Method not found */ 
     log.error("Validator method not found."); 
     return false; 
    } 
    } 

} 

この制約は、より多くの制約を定義する場合に便利です。そして、あなたはオフトピックなど、検証や複数の検証を追加するための条件のような複数の特徴と

それを拡張することができます:検証は春ブーツとは何の関係もありません

  • そうする必要はありませんあなたの質問に言及してください。

  • serialVersionUID = 1L;非常に悪い考えです。 IDE serialVersionUIDジェネレーターを使用して、このフィールドに1Lと異なる値を入力します。

0

@NotNull 
@Size(min=1) 
private String description; 

これは私が考えることができることを探している最善の方法です。