2009-05-26 7 views
18

मैं सिर्फ हाइबरनेट के साथ शुरू हो रही है, और सभी उदाहरण मैं अब तक काफी देखने हाइबरनेट दस्तावेज में ट्यूटोरियल की तरह दिखाई दे रही है:क्या हाइबरनेट-प्रबंधित ऑब्जेक्ट्स के लिए अंतिम फ़ील्ड घोषित करने का कोई तरीका है?

package org.hibernate.tutorial.domain; 
import java.util.Date; 

public class Event { 

    private Long id; 
    private String title; 
    private Date date; 

    public Event() {} 

    /* Accessor methods... */ 
} 

विशेष रूप से: खेतों में से कोई भी final के रूप में घोषित कर रहे हैं, और वहां कोई तर्क-तर्क कन्स्ट्रक्टर होना चाहिए ताकि हाइबरनेट फ्रेमवर्क कक्षा को तुरंत चालू कर सके और अपने फ़ील्ड सेट कर सके।

लेकिन यहाँ बात है - मैं वास्तव में मेरी कक्षाएं किसी भी तरह से परिवर्तनशील बनाने पसंद नहीं है जब भी मैं यह बच सकते हैं (जावा प्रथाएं: अपरिवर्तनीय वस्तुओं ऐसा करने के लिए एक बहुत मजबूत तर्क हैं)। तो क्या हाइबरनेट को काम करने का कोई तरीका है, भले ही मैं प्रत्येक फ़ील्ड 'अंतिम' घोषित करना चाहता हूं?

मैं समझता हूं कि हाइबरनेट अपने वर्गों को तुरंत चालू करने के लिए प्रतिबिंब का उपयोग करता है और इसलिए जोखिम लेने के बिना किसी प्रकार के कन्स्ट्रक्टर का आह्वान करने में सक्षम होना चाहिए कि यह गलत कन्स्ट्रक्टर चुनता है या इसके मानकों में से किसी एक को गलत मान देता है, इसलिए नो-एर्ग कन्स्ट्रक्टर का आह्वान करना संभव है और एक ही समय में प्रत्येक फ़ील्ड को सेट करना सुरक्षित है। हालांकि, क्या आवश्यक जानकारी को हाइबरनेट को प्रदान करना संभव नहीं है ताकि यह सुरक्षित रूप से अपरिवर्तनीय वस्तुओं को तुरंत चालू कर सके?

public class Event { 

    private final Long id; 
    private final String title; 
    private final Date date; 

    public Event(@SetsProperty("id") Long id, 
     @SetsProperty("title") String title, 
     @SetsProperty("date") Date date) { 

     this.id = id; 
     this.title = title; 
     this.date = new Date(date.getTime()); 
    } 

    /* Accessor methods... */ 
} 

@SetsProperty एनोटेशन फर्जी निश्चित रूप से है, लेकिन नहीं लगता है जैसे कि यह पहुँच से बाहर किया जाना चाहिए।

उत्तर

5

यह लग रहा है जैसे कि यह हाइबरनेट के लिए एक उपयोग मामला नहीं है, कई आपरेशनों के बाद से यह चिंता का विषय परिवर्तनशील राज्य करता है:

  • विलय वस्तुओं
  • गंदी स्थिति की जाँच
  • फ्लशिंग में परिवर्तन

ऐसा कहा जा रहा है कि, यदि आप अपरिवर्तनीयता के बारे में चिंतित हैं तो आप कॉपी-कन्स्ट्रक्टर के साथ अपनी ऑब्जेक्ट्स के चारों ओर रैपर प्रदान करना चुन सकते हैं:

public class FinalEvent { 
    private final Integer id; 

    public FinalEvent(Event event) { 
     id = event.id; 
    } 
} 

इसका मतलब अतिरिक्त काम है।


अब जब कि मैं इसके बारे में सोच रहा हूँ, हाइबरनेट सत्र आमतौर पर धागा बाध्य कर रहे हैं और यह कम से कम एक अंतिम क्षेत्रों के लाभों को निरस्त हो जाती है - सुरक्षित प्रकाशन।

अंतिम फ़ील्ड के अन्य लाभ क्या आप ढूंढ रहे हैं?

+1

+1: एक रैपर वर्ग का उपयोग करने पर अच्छा विचार - ऐसा लगता है कि अंतिम कक्षा/फ़ील्ड की आवश्यकता होने पर यह एक अच्छा समाधान होगा। कोई भी अजीबता से बच सकता है जिस पर संस्करण (उत्परिवर्तनीय बनाम रैपर) को उत्परिवर्तनीय संस्करण केवल डेटा एक्सेस कक्षाओं में दिखाई देकर बाहरी रूप से उपयोग किया जाना चाहिए। अंतिम का उपयोग करने के लिए, मेरा मुख्य कारण यह है कि गारंटी देने के बजाय अक्सर यह सुनिश्चित करना आसान होता है कि प्रत्येक फ़ील्ड को निर्माण पर बिल्कुल एक बार असाइन किया जाता है। हमारे पास बहुत सारे डेटा हैं जो कि जेवीएम के पूरे जीवन में निरंतर रहना है जो इसका उपयोग करता है, इसलिए यह स्पष्ट करना उपयोगी होता है। –

+1

अंतिम फ़ील्ड किसी उपयोगकर्ता को गलती से असाइन करने से रोकती हैं जो उनके पास नहीं होनी चाहिए और सूक्ष्म बग पेश करना चाहिए। यदि आप जानते हैं कि कुछ कभी नहीं बदलेगा, तो आप इसे अंतिम बनाना चाहते हैं। सड़क के नीचे यदि आपको लगता है कि इसे बदलना चाहिए, तो आप हमेशा उस बाधा को हटा सकते हैं। – corsiKa

13

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

+4

+1: धन्यवाद - यह भी सहायक है (सेटर्स को हटाकर और क्षेत्र-आधारित पहुंच का उपयोग करके) उन मामलों के लिए जहां एक रैपर वर्ग बनाने के लिए संभव/व्यावहारिक नहीं है। ऐसा नहीं कह सकता क्योंकि मैं दृश्यों के पीछे चल रहा है कि रिफ्लेक्शन कुंग-फु के प्रकार से बहुत रोमांचित हूं - निजी क्षेत्र जो वास्तव में निजी नहीं हैं और सभी। मुझे ऐसा लगता है कि मुझे कुछ @ReadTheHibernateBookBeforeUsingThisClass टैग उपयोगकर्ताओं (जैसे मेरे) में जोड़ना चाहिए जो हाइबरनेट कैसे काम करता है, इस विवरण से परिचित नहीं हैं। –

2

आप बिल्डर पैटर्न का उपयोग करके वांछित परिणाम पूरा करने में सक्षम हो सकते हैं। मैंने थोड़ी देर पहले इस विचार पर चर्चा करने वाले हाइबरनेट फ़ोरम पर posting पढ़ा था (हालांकि मैंने इसे कभी भी लागू नहीं किया ...)

4

यह मुझे लंबे समय तक भी परेशान कर रहा है।एक विचार जो मैं हाल ही में कोशिश कर रहा हूं वह यह है - अपने मॉडल वर्गों के लिए केवल पढ़ने के लिए इंटरफेस को परिभाषित करें और अपने डीएओ और किसी भी कारखानों को ऑब्जेक्ट पर बदले में वापस कर दें। इसका मतलब है कि कार्यान्वयन म्यूटेबल है, भले ही इसे डीएओ/फैक्ट्री ऑब्जेक्ट छोड़ दिया जाए, इसे अब tweaked नहीं किया जा सकता है।

तो जैसा

:

public interface Grape { 
    public Color getColor(); 
} 

public class HibernateGrapeDao { 
    public Grape findGrape(int grapeId) { 
    HibernateGrape grape = hibernate.find(... 
    return grape; 
    } 
} 

class HibernateGrape implements Grape { 
.... 
} 

भी लागू करने कक्षाएं पैकेज-निजी दाव पैकेज के लिए रखना चाहते हैं सकता है, तो कोई भी उनके साथ सीधे बेला कर सकते हैं। थोड़ा और काम, लेकिन शायद लंबे समय तक चीजों को क्लीनर रखने में मदद करता है। और जाहिर है, पूरी समानता/पहचान व्यवसाय से सावधान रहें।

10

वास्तव में जेडीके 1.5+ हाइबरनेट में अंतिम फ़ील्ड बदलने (प्रतिबिंब के माध्यम से) संभाल सकता है। एक संरक्षित डिफ़ॉल्ट कन्स्ट्रक्टर() बनाएं जो फ़ील्ड को कुछ डिफ़ॉल्ट/शून्य आदि पर सेट करता है ... हाइबरनेट ऑब्जेक्ट को तत्काल करने पर उन मानों को ओवरराइड कर सकता है और ओवरराइड कर देगा।

यह जावा 1.5 मेमोरी मॉडल में परिवर्तन के लिए सभी संभव धन्यवाद है - ब्याज के परिवर्तन (अंतिम रूप से अंतिम नहीं होने की अनुमति देता है) जहां क्रमबद्धता/deserialization सक्षम करने के लिए बनाया गया है।

public class Event { 

private final Long id; 
private final String title; 
private final Date date; 

// Purely for serialization/deserialization 
protected Event() { 
    id = null; 
    title = null; 
    date = null; 
} 

public Event(Long id, String title, Data date) { 
    this.id = id; 
    this.title = title; 
    this.date = date; 
} 

/* Accessor methods... */ 

}

0

@Access (AccessType.FIELD) के साथ अपने वर्ग पर टिप्पणी करें तो आप अपने क्षेत्रों अंतिम बना सकते हैं। इस तरह:

@Access(AccessType.FIELD) 
public final class Event { 

    private final Long id; 
    private final String title; 
    private final Date date; 

    private Event() { 
     id = null; 
     title = null; 
     date = null; 
    } 

    public Event(Long id, String title, Date date) { 
     this.id = id; 
     this.title = title; 
     this.date = date; 
    } 
} 
संबंधित मुद्दे

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