2010-12-30 10 views
14

हमारे हाइबरनेट परियोजना में, इकाइयों को जावा बीन्स पैटर्न का उपयोग करके कोड किया जाता है। हमारे कोड में बहुत से स्पॉट हैं जहां कोई म्यूटेटर सेट करने के लिए भूल गया है और हमें न्यूल फील्ड के कारण अपवाद मिलता है।अपरिवर्तनीय जेपीए इकाइयां संभव है?

क्या कोई भी बिल्डरों का उपयोग अपनी संस्थाओं को बनाने या उन्हें अपरिवर्तनीय बनाने के लिए कर रहा है?

मैं एक प्रभावी पैटर्न खोजने की कोशिश कर रहा हूं जो जावा बीन्स पैटर्न की शैली में नहीं है।

धन्यवाद

उत्तर

14

आप अपने सेम अपरिवर्तनीय करते हैं तो आप क्षेत्र स्तर तक पहुँच का उपयोग करना होगा और के रूप में अच्छी तरह से विचार-विमर्श किया here इस समस्याओं के अपने स्वयं के सेट के साथ आता है। हमारे द्वारा लिया गया दृष्टिकोण एक बिल्डर/कारखाना है जो हमारे लिए अनिवार्यता आदि नियमों को लागू/मान्य करता है।

+0

को जोड़ने के लिए, आप के निर्माण के लिए एक बिल्डर का उपयोग कर रहे हैं इकाई, लेकिन अभी भी mutators है? क्या आप थोड़ा सा विस्तार कर सकते हैं? –

+3

यह वही है जो हम करते हैं (यह सभी अनुप्रयोगों पर वैश्विक रूप से लागू नहीं हो सकता है)। मान लें कि हमारे पास एक क्लास व्यक्ति है। उसके बाद हमारे पास PersonFactoryBuilder होगा जो एक व्यक्ति ऑब्जेक्ट बनाएगा लेकिन इसे रीडेबलपर्सन में डालेगा। पठनीय पर्सन एक इंटरफ़ेस है जो केवल "प्राप्त" विधियों को उजागर करता है जिससे इसे अपरिवर्तनीय बना दिया जाता है। डीबी से प्राप्त करते समय, हमारे पास पर्सनल रिपोजिटरी (डीएओ की तरह) होती है, जो व्यक्ति को डीबी से प्राप्त करती है और इरादे (अपडेट या डिस्प्ले) के आधार पर इसे रीड करने योग्य या व्यक्ति (उत्परिवर्तनीय) देता है। यह डिजाइन जोडा-टाइम लाइब्रेरी से प्रेरित था। http://joda-time.sourceforge.net –

+1

इंटरफेस पर कास्टिंग! अमूर्तता के लिए हुरेय। यह एक लाजवाब विचार है। धन्यवाद। – b3bop

8

हमारी परियोजना में हम वेनिला बिल्डर्स दृष्टिकोण (@see प्रभावी जावा) का उपयोग करते हैं। निम्न उदाहरण पर विचार करें:

@Entity 
public class Person { 
    public static class Builder { 
     private String firstName; 
     private String lastName; 
     private PhoneNumber phone; 

     public Builder() {} 

     public Builder withFullName(String fullName) { 
      Preconditions.notNull(fullName); 
      String[] split = fullName.split(" "); 
      if (split == null || split.length != 2) { 
       throw new IllegalArgumentException("Full name should contain First name and Last name. Full name: " + fullName); 
      } 
      this.firstName = split[0]; 
      this.lastName = split[1]; 
      return this; 
     } 

     public Builder withPhone(String phone) { 
      // valueOf does validation 
      this.phone = PhoneNumber.valueOf(phone); 
      return this; 
     } 

     public Person build() { 
      return new Person(this); 
     } 
    } 

    //@Columns 
    private long id;//@Id 
    private String firstName; 
    private String lastName; 
    private String phoneNumber; 

    // hibernate requires default constructor 
    private Person() {} 

    private Person(Builder builder) { 
     this.firstName = Preconditions.notNull(builder.firstName); 
     this.lastName = Preconditions.notNull(builder.lastName); 
     this.phoneNumber = builder.phone != null ? builder.phone : null; 
    } 

    //Getters 
    @Nonnull 
    public String getFirstName() { return firstName;} 
    @Nonnull 
    public String getLastName() { return lastName;} 
    @Nullable 
    public String getPhoneName() { return phone;} 
    public long getId() { return id;} 
} 

मामले में आप कभी कभी इकाई मैं new Builder(Person person) जो सभी डेटा वापस की प्रतिलिपि बनाएगा शुरू करने की सिफारिश करेंगे उत्परिवर्तित करना चाहते हैं, तो आप बिल्डर के साथ उत्परिवर्तित कर सकते हैं। बेशक यह नई इकाई का उत्पादन करेगा, इसलिए पुराना केवल पढ़ा जाता है।

(उत्परिवर्तन) के साथ उपयोग के रूप में सरल है:

Person.Builder personBuilder = new Person.Builder(); 
Person person = personBuilder.withFullName("Vadim Kirilchuk").withPhone("12345678").build(); 

Person modified = new Person.Builder(person).withPhone("987654321").build(); 

यह भी ध्यान दें कि इस उदाहरण व्यक्ति में महत्वपूर्ण है 100% अपरिवर्तनीय नहीं है (और नहीं हो सकता है) वर्ग: सब से पहले क्योंकि आईडी जेपीए द्वारा निर्धारित किया जाएगा, आलसी संघों को रनटाइम पर भी लाया जा सकता है और आखिरकार क्योंकि आपके पास फ़ील्ड फ़ाइनल नहीं हो सकता है (आवश्यक डिफ़ॉल्ट कन्स्ट्रक्टर के कारण) :(बाद वाला बिंदु मल्टीथ्रेडेड वातावरण के लिए भी चिंता का विषय है, यानी यह यह संभव है कि #build() के बाद इकाई किसी अन्य धागे को पास कर दे, सभी प्रकार की त्रुटियों का कारण बन सकती है क्योंकि अदर थ्रेड को पूरी तरह से निर्मित ऑब्जेक्ट देखने की गारंटी नहीं है।

जेपीए 2.1 विनिर्देश, अनुभाग "2.1 इकाई कक्षा", कहते हैं:

की कोई विधि या संस्था वर्ग की लगातार उदाहरण चर अंतिम हो सकता है।

एक और समान दृष्टिकोण: http://vlkan.com/blog/post/2015/03/21/immutable-persistence/

मेरे मामले में मैं सिर्फ आईडी बिल्डर बजाय ड्राफ्ट के शीर्ष पर निर्माण सेवा ..

तो
संबंधित मुद्दे