JPA मल्टीपल एंबेडेड फ़ील्ड


84

क्या एक जेपीए इकाई वर्ग के लिए दो एम्बेडेड ( @Embedded) फ़ील्ड शामिल करना संभव है ? एक उदाहरण होगा:

@Entity
public class Person {
    @Embedded
    public Address home;

    @Embedded
    public Address work;
}

public class Address {
    public String street;
    ...
}

इस मामले Personमें दो Addressउदाहरण हो सकते हैं - घर और काम। मैं JPA का उपयोग हाइबरनेट के कार्यान्वयन के साथ कर रहा हूं। जब मैं हाइबरनेट टूल्स का उपयोग करके स्कीमा उत्पन्न करता हूं, तो यह केवल एक एम्बेड करता है Address। मुझे क्या पसंद है दो एम्बेडेड Addressउदाहरण हैं, प्रत्येक अपने स्तंभ नामों के साथ प्रतिष्ठित हैं या कुछ उपसर्ग (जैसे घर और काम) के साथ पूर्व-लंबित हैं। मुझे पता है @AttributeOverrides, लेकिन इसके लिए जरूरी है कि प्रत्येक विशेषता को व्यक्तिगत रूप से ओवरराइड किया जाए। यदि Addressप्रत्येक स्तंभ को व्यक्तिगत रूप से ओवरराइड करने की आवश्यकता होती है, तो यह बोझिल हो सकता है।

जवाबों:


28

यदि आप एक ही इकाई में दो बार एक ही एम्बेड करने योग्य ऑब्जेक्ट प्रकार रखना चाहते हैं, तो स्तंभ नाम डिफ़ॉल्ट रूप से काम नहीं करेगा: कम से कम एक कॉलम को स्पष्ट करना होगा। हाइबरनेट EJB3 कल्पना से परे है और आपको NamingStrategy के माध्यम से डिफ़ॉल्ट तंत्र को बढ़ाने की अनुमति देता है। DefaultComponentSafeNamingStrategy डिफ़ॉल्ट EJB3NamingStrategy पर एक छोटा सा सुधार है जो एम्बेडेड ऑब्जेक्ट्स को एक ही इकाई में दो बार उपयोग किए जाने पर भी डिफ़ॉल्ट होने की अनुमति देता है।

हाइबरनेट एनोटेशन से डॉक्टर: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e714


89

ऐसा करने का सामान्य जेपीए तरीका @AttributeOverride है। यह एक्लिप्सलिंक और हाइबरनेट दोनों में काम करना चाहिए।

@Entity 
public class Person {
  @AttributeOverrides({
    @AttributeOverride(name="street",column=@Column(name="homeStreet")),
    ...
  })
  @Embedded public Address home;

  @AttributeOverrides({
    @AttributeOverride(name="street",column=@Column(name="workStreet")),
    ...
  })
  @Embedded public Address work;
  }

  @Embeddable public class Address {
    @Basic public String street;
    ...
  }
}

9
ध्यान दें कि name="street"संपत्ति के नाम को संदर्भित करता है, कॉलम नाम को नहीं।
बार्ट स्वेनहुइस

क्या इसे "क्लंकी" माना जाता है, क्योंकि इसमें व्यक्ति के डेवलपर को क्लास एड्रेस (सड़क का नाम रखने वाले क्षेत्र का नाम) जैसी अंतरंग बातों को जानना आवश्यक है?
mbmast

वाह, इसलिए मुझे एनोटेशन का उपयोग करके इसे दोहराना होगा। WTF। मैं बस के रूप में अच्छी तरह से पूरी तरह से एम्बेडेड वर्ग खुद को घोषित करने के लिए स्ट्रिंग होमवर्क का उपयोग कर सकता है; स्ट्रिंग वर्कस्ट्रीट के बजाय, शायद अधिक निर्धारक।
एमएमएम

6

ग्रहण लिंक का उपयोग करते समय, AttributeOverrides का उपयोग करने के लिए एक विकल्प एक सत्र-कस्टमाइज़र का उपयोग करने के लिए। यह एक बार में सभी संस्थाओं के लिए समस्या हल करती है:

public class EmbeddedFieldNamesSessionCustomizer implements SessionCustomizer {

@SuppressWarnings("rawtypes")
@Override
public void customize(Session session) throws Exception {
    Map<Class, ClassDescriptor> descriptors = session.getDescriptors();
    for (ClassDescriptor classDescriptor : descriptors.values()) {
        for (DatabaseMapping databaseMapping : classDescriptor.getMappings()) {
            if (databaseMapping.isAggregateObjectMapping()) {
                AggregateObjectMapping m = (AggregateObjectMapping) databaseMapping;
                Map<String, DatabaseField> mapping = m.getAggregateToSourceFields();

                ClassDescriptor refDesc = descriptors.get(m.getReferenceClass());
                for (DatabaseMapping refMapping : refDesc.getMappings()) {
                    if (refMapping.isDirectToFieldMapping()) {
                        DirectToFieldMapping refDirectMapping = (DirectToFieldMapping) refMapping;
                        String refFieldName = refDirectMapping.getField().getName();
                        if (!mapping.containsKey(refFieldName)) {
                            DatabaseField mappedField = refDirectMapping.getField().clone();
                            mappedField.setName(m.getAttributeName() + "_" + mappedField.getName());
                            mapping.put(refFieldName, mappedField);
                        }
                    }

                }
            }

        }
    }
}

}

+1 को डिस्क्रिप्टिव कस्टूमाइज़र के रूप में रखना अच्छा होगा, इस प्रति वर्ग को नियंत्रित करने में सक्षम होने के लिए, लेकिन मुझे मेजबान वर्ग के डिसिप्लॉर कस्टूमाइज़र के भीतर से एम्बेडेड क्लास के क्लासडेसिप्टर तक पहुंचने का कोई रास्ता नहीं मिला है।
enzलॉन्ज

1
अब मैं जिस विकल्प का उपयोग कर रहा हूं, classDescriptor.getJavaClass()वह है कि मैं जिस वर्ग को प्रभावित करना चाहता हूं, उसकी एक सूची के खिलाफ SessionCustomizer में जांच करें ।
oulenz

1

यदि आप हाइबरनेट का उपयोग कर रहे हैं तो आप एक अलग नामकरण योजना का उपयोग कर सकते हैं जो समान एम्बेडेड क्षेत्रों के लिए स्तंभों के लिए अद्वितीय उपसर्ग जोड़ता है। @Embeddable Classes के लिए कॉलम नामों में स्वचालित रूप से एक उपसर्ग जोड़ें देखें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.