मैं संयोजन में दो या अधिक क्षेत्रों को कैसे मान्य कर सकता हूं?


92

मैं अपने मॉडल को मान्य करने के लिए JPA 2.0 / हाइबरनेट सत्यापन का उपयोग कर रहा हूं। अब मेरे पास एक ऐसी स्थिति है जहां दो क्षेत्रों के संयोजन को मान्य किया जाना है:

public class MyModel {
    public Integer getValue1() {
        //...
    }
    public String getValue2() {
        //...
    }
}

मॉडल है अमान्य अगर दोनों getValue1()और getValue2()कर रहे हैं nullऔर वैध अन्यथा।

मैं JPA 2.0 / हाइबरनेट के साथ इस तरह का सत्यापन कैसे कर सकता हूं? एक साधारण @NotNullएनोटेशन के साथ सत्यापन प्राप्त करने के लिए दोनों गेटर्स गैर-शून्य होना चाहिए।


जवाबों:


102

कई गुणों के सत्यापन के लिए, आपको कक्षा-स्तर की बाधाओं का उपयोग करना चाहिए। से बीन मान्यकरण एक नज़र भाग द्वितीय: कस्टम की कमी :

### कक्षा-स्तर की बाधाएँ

आप में से कुछ लोगों ने कई गुणों के साथ एक बाधा को लागू करने की क्षमता, या बाधा को व्यक्त करने की क्षमता के बारे में चिंता व्यक्त की है जो कई गुणों पर निर्भर करती है। शास्त्रीय उदाहरण पता मान्यता है। पते जटिल नियम हैं:

  • सड़क का नाम कुछ हद तक मानक है और निश्चित रूप से इसकी लंबाई सीमा होनी चाहिए
  • ज़िप कोड संरचना पूरी तरह से देश पर निर्भर करती है
  • शहर को अक्सर एक ज़िपकोड से संबद्ध किया जा सकता है और कुछ त्रुटि जाँच की जा सकती है (बशर्ते कि एक सत्यापन सेवा सुलभ हो)
  • इन अन्योन्याश्रितियों के कारण एक साधारण संपत्ति स्तर की बाधा बिल को फिट करने के लिए करती है

बीन सत्यापन विनिर्देश द्वारा प्रस्तुत समाधान दो गुना है:

  • यह समूहों और समूह अनुक्रमों के उपयोग के माध्यम से बाधाओं के एक अन्य सेट से पहले लागू होने के लिए बाधाओं का एक सेट लागू करने की क्षमता प्रदान करता है। यह विषय अगली ब्लॉग प्रविष्टि में शामिल किया जाएगा
  • यह वर्ग स्तर की बाधाओं को परिभाषित करने की अनुमति देता है

कक्षा स्तर की बाधाएं नियमित बाधाएं हैं (एनोटेशन / कार्यान्वयन जोड़ी) जो एक संपत्ति के बजाय एक वर्ग पर लागू होती हैं। अलग तरह से कहा, वर्ग-स्तर की बाधाओं में (उदाहरण के बजाय संपत्ति के मूल्य) वस्तु उदाहरण प्राप्त करते हैं isValid

@AddressAnnotation 
public class Address {
    @NotNull @Max(50) private String street1;
    @Max(50) private String street2;
    @Max(10) @NotNull private String zipCode;
    @Max(20) @NotNull String city;
    @NotNull private Country country;
    
    ...
}

@Constraint(validatedBy = MultiCountryAddressValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AddressAnnotation {
    String message() default "{error.address}";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
}

public class MultiCountryAddressValidator implements ConstraintValidator<AddressAnnotation, Address> {
    public void initialize(AddressAnnotation constraintAnnotation) {
    // initialize the zipcode/city/country correlation service
    }

    /**
     * Validate zipcode and city depending on the country
     */
    public boolean isValid(Address object, ConstraintValidatorContext context) {
        if (!(object instanceof Address)) {
            throw new IllegalArgumentException("@Address only applies to Address");
        }
        Address address = (Address) object;
        Country country = address.getCountry();
        if (country.getISO2() == "FR") {
            // check address.getZipCode() structure for France (5 numbers)
            // check zipcode and city correlation (calling an external service?)
            return isValid;
        } else if (country.getISO2() == "GR") {
            // check address.getZipCode() structure for Greece
            // no zipcode / city correlation available at the moment
            return isValid;
        }
        // ...
    }
}

उन्नत पता सत्यापन नियमों को पता ऑब्जेक्ट से बाहर छोड़ दिया गया है और इसके द्वारा कार्यान्वित किया गया है MultiCountryAddressValidator। ऑब्जेक्ट इंस्टेंस तक पहुँचने से, क्लास स्तर की बाधाओं में बहुत अधिक लचीलापन होता है और यह कई सहसंबद्ध गुणों को मान्य कर सकता है। ध्यान दें कि आदेश यहां समीकरण से बाहर है, हम अगली पोस्ट में इसे वापस आएंगे।

विशेषज्ञ समूह ने विभिन्न गुण गुणों के दृष्टिकोण पर चर्चा की है: हमें लगता है कि वर्ग स्तर की बाधा दृष्टिकोण निर्भरता वाले अन्य संपत्ति स्तर दृष्टिकोणों की तुलना में पर्याप्त सादगी और लचीलापन दोनों प्रदान करता है। आपकी प्रतिक्रिया का स्वागत है।


17
इंटरफ़ेस कांस्ट्रेविलेविलेटर और एनोटेशन @ कॉनस्ट्रैटिन को उदाहरण में उलटा किया गया है। और वैध है () 2 पैरामीटर लेता है।
गुइलुमे हस्टा

1
TYPEऔर क्रमशः के RUNTIMEसाथ ElementType.TYPEऔर प्रतिस्थापित किया जाना चाहिए RetentionPolicy.RUNTIME
mark.monteiro

2
@ mark.monteiro आप स्थिर आयात का उपयोग कर सकते हैं: import static java.lang.annotation.ElementType.*;औरimport static java.lang.annotation.RetentionPolicy.*;
cassiomolin

2
मैंने बीन सत्यापन के साथ काम करने के लिए उदाहरण को फिर से लिखा है। यहाँ एक नज़र है
कैसियोमोलिन

1
एनोटेशन के पैरामीटर विनिर्देश के भीतर सही नहीं हैं, क्योंकि इस उत्तर के तहत कैसियो द्वारा उल्लेखित एक संदेश, समूह, और पेलोड होना चाहिए।
पीटर एस।

38

बीन मान्यकरण के साथ ठीक से काम करने के लिए, पास्कल थिवेंट के उत्तर में दिए गए उदाहरण को इस प्रकार फिर से लिखा जा सकता है:

@ValidAddress
public class Address {

    @NotNull
    @Size(max = 50)
    private String street1;

    @Size(max = 50)
    private String street2;

    @NotNull
    @Size(max = 10)
    private String zipCode;

    @NotNull
    @Size(max = 20)
    private String city;

    @Valid
    @NotNull
    private Country country;

    // Getters and setters
}
public class Country {

    @NotNull
    @Size(min = 2, max = 2)
    private String iso2;

    // Getters and setters
}
@Documented
@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy = { MultiCountryAddressValidator.class })
public @interface ValidAddress {

    String message() default "{com.example.validation.ValidAddress.message}";

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

    Class<? extends Payload>[] payload() default {};
}
public class MultiCountryAddressValidator 
       implements ConstraintValidator<ValidAddress, Address> {

    public void initialize(ValidAddress constraintAnnotation) {

    }

    @Override
    public boolean isValid(Address address, 
                           ConstraintValidatorContext constraintValidatorContext) {

        Country country = address.getCountry();
        if (country == null || country.getIso2() == null || address.getZipCode() == null) {
            return true;
        }

        switch (country.getIso2()) {
            case "FR":
                return // Check if address.getZipCode() is valid for France
            case "GR":
                return // Check if address.getZipCode() is valid for Greece
            default:
                return true;
        }
    }
}

CDI बीन के लिए WebSphere restful प्रोजेक्ट में कस्टम सत्यापनकर्ता को बूटस्ट्रैप या आमंत्रित कैसे करें? मैंने सभी लिखा है, लेकिन कस्टम बाधा काम नहीं कर रही है या आमंत्रित नहीं है
बालाजीचंदर

मैं एक समान सत्यापन के साथ फंस गया हूं, लेकिन मेरा isoA2CodeDB Countryतालिका में संग्रहित है । क्या यहां से डीबी कॉल करना एक अच्छा विचार है? इसके अलावा, मैं सत्यापन के बाद उन्हें लिंक करने के लिए चाहते हैं क्योंकि Address belongs_toएक Countryऔर मैं चाहता हूँ addressप्रविष्टि के लिए countryमेज के विदेशी कुंजी। मैं देश को संबोधन से कैसे जोड़ूंगा?
क्रोजाइन

ध्यान दें कि जब आप किसी गलत ऑब्जेक्ट पर एक प्रकार का सत्यापन एनोटेशन सेट करेंगे, तो बीन सत्यापन फ्रेमवर्क द्वारा एक अपवाद फेंक दिया जाएगा। उदाहरण के लिए यदि आप @ValidAddressदेश ऑब्जेक्ट पर एनोटेशन सेट करते हैं, तो आपको एक No validator could be found for constraint 'com.example.validation.ValidAddress' validating type 'com.example.Country'अपवाद मिलेगा ।
याकूब वैन लिंगन

12

एक कस्टम क्लास लेवल वैलिनेटर जाने का रास्ता है, जब आप बीन वैलिडेशन विनिर्देश के साथ रहना चाहते हैं, तो यहां उदाहरण दें ।

यदि आप हाइबरनेट वैलिडेटर सुविधा का उपयोग करके खुश हैं, तो आप @ScriptAssert का उपयोग कर सकते हैं , जो कि Validator-4.1.0.Final के बाद से प्रदान किया गया है। अपने JavaDoc से Exceprt:

स्क्रिप्ट अभिव्यक्ति किसी भी स्क्रिप्टिंग या अभिव्यक्ति भाषा में लिखी जा सकती है, जिसके लिए एक JSR 223 ("JavaTM प्लेटफ़ॉर्म के लिए स्क्रिप्टिंग") संगत इंजन क्लासपाथ पर पाया जा सकता है।

उदाहरण:

@ScriptAssert(lang = "javascript", script = "_this.value1 != null || _this != value2)")
public class MyBean {
  private String value1;
  private String value2;
}

हां, और जावा 6 में राइनो (जावास्क्रिप्ट इंजन) शामिल है, ताकि आप अतिरिक्त निर्भरता को जोड़े बिना जावास्क्रिप्ट को अभिव्यक्ति भाषा के रूप में उपयोग कर सकें।

3
यहाँ एक उदाहरण है कि कैसे हाइबरनेट वैलिडेटर के साथ 5.1.1.Final
इवान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.