5

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

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@Table(name = "client") 
public abstract class Client extends AbstractPersistable<Long> { 
    // ... 
} 

आवेदन एक:

@Entity 
public class ClientSimple extends Client { 
    private String name; 
    // getter, setter 
} 

आवेदन बी: ​​

@Entity 
public class ClientAdvanced extends Client { 
    private String description; 
    // getter, setter 
} 

अब एक डीएओ आवेदन ए और बी के लिए Client ऑब्जेक्ट्स के साथ काम कर सकता है लेकिन एप्लिकेशन बी अपने क्लाइंट ऑब्जेक्ट के लिए अतिरिक्त जानकारी को परिभाषित कर सकता है जिसे मैनेजर विधि यूनिक द्वारा पढ़ा जा सकता है

आवेदन एक:: आवेदन बी ई

Client client = new ClientSimple(); 
clientDao.save(client); 

आवेदन बी: ​​

Client client = new ClientAdvanced(); 
clientDao.save(client); 

दुर्भाग्य से इसका मतलब यह है कि हर तालिका में एक DTYPE स्तंभ (या किसी अन्य नाम है कि मैं चुन सकते हैं) है । क्या इससे छुटकारा पाने का कोई तरीका है? हमें इसकी आवश्यकता नहीं है और यह डीबी स्पेस का उपयोग कर रहा है ...

धन्यवाद!


संपादित

नोट करने के लिए महत्वपूर्ण: @MappedSuperclass काम नहीं करेगा। हम QueryDSL हमारे एचक्यूएल एब्स्ट्रक्शन लेयर के रूप में उपयोग कर रहे हैं। क्वेरी सहेजने के लिए इसे स्वचालित रूप से जेनरेट की गई क्वेरी प्रकार कक्षाओं की आवश्यकता होती है। हालांकि, अगर अमूर्त वर्ग @Entity के साथ एनोटेट किया गया है तो ये केवल सही ढंग से उत्पन्न किए जाएंगे।

यह neccessairy है क्योंकि हम सार वर्ग Client के खिलाफ क्वेरी करने के लिए है, जबकि सच्चाई में आवेदन एक में ClientSimple और ClientAdvanced क्वेरी करने आवेदन बी में हैं:

तो किसी भी आवेदन में यह काम करेगा:

query.where(QClient.client.name.equals("something"); 

और आवेदन बी में यह काम करेगा:

query.where(QClientSimple.client.description.equals("something else"); 

EDIT2 - उबाल नीचे

यह इस के लिए नीचे उबालने के लिए लगता है: मैं तैनाती समय में हाइबरनेट एक निश्चित मूल्य के लिए एक inhertited इकाई के लिए discriminator प्रकार सेट करने के लिए कॉन्फ़िगर कर सकते हैं। तो मेरे उदाहरण के साथ एक Client एक आवेदन में ClientSimple और दूसरे में ClientAdvanced होगा ताकि मुझे उस जानकारी को डेटाबेस में संग्रहीत करने की आवश्यकता न हो?

जैसा कि मैंने कहा था: प्रत्येक एप्लिकेशन बेस एप्लिकेशन स्टैक का एक उदाहरण होगा। प्रत्येक एप्लिकेशन अपने स्थानीय डेटाबेस के लिए अतिरिक्त कॉलम परिभाषित कर सकता है लेकिन सभी ऑब्जेक्ट्स उस उदाहरण के लिए एक ही प्रकार के होंगे, इसलिए हम गारंटी देते हैं कि भेदभावकर्ता हमेशा डेटाबेस में अनावश्यक बना देता है और हाइबरनेट कॉन्फ़िगरेशन के लिए उपयोग केस बनाता है।

+0

आप किस क्वेरीबेल संस्करण का उपयोग कर रहे हैं? –

+0

हम QueryDSL 2.2.3 का उपयोग कर रहे हैं, लेकिन अगर नए संस्करण मैप किए गए सुपरक्लास को क्वेरी लक्ष्यों के रूप में समर्थन देते हैं तो अपडेट कर सकते हैं: इस तरह: '@ मैपड सुपरपरक्लास @टेबल पब्लिक अमूर्त क्लास क्लाइंट ... '+' @ एंटीटी पब्लिक क्लास क्लाइंटसिंपल क्लाइंट का विस्तार करता है == > क्वेरी प्रकार उत्पन्न करें ... ==> क्वेरी: 'QClient.client.name' – Pete

+1

यह सीधे समर्थित नहीं है, लेकिन आप इसके लिए गिटहब पर टिकट जोड़ सकते हैं। यह आसानी से लागू किया गया है। –

उत्तर

1

आप Client@MappedSuperclass बजाय @Entity के रूप में घोषणा कर सकते हैं आप एक ही आवेदन में ClientSimple और ClientAdvanced दोनों का उपयोग करने की आवश्यकता नहीं है।

+0

दुर्भाग्य से यह संभव नहीं है। हम क्वेरी डीएसएल का उपयोग हमारे एचक्यूएल एब्स्ट्रक्शन लेयर के रूप में कर रहे हैं। इसके लिए अमूर्त वर्गों को @Entity को एनोटेट करने की आवश्यकता है ताकि वास्तव में विस्तार से पूछताछ करते समय एक क्वेरी को अमूर्त वर्ग के विरुद्ध चलाया जा सके। मैं इस सीमा को दर्शाने के लिए अपनी पोस्ट संपादित करूंगा। – Pete

1

हाइबरनेट में, प्रति वर्ग पदानुक्रम में एकल तालिका हमेशा इकाइयों के बीच अंतर करने के लिए एक भेदभावकर्ता कॉलम की आवश्यकता होगी क्योंकि एक पदानुक्रम में सभी वर्ग एक तालिका में संग्रहीत होते हैं। यहां Hibernate Single Table per Class Hierarchy का एक उदाहरण है।

लेकिन तुम पर विचार करने के लिए नीचे दिए गए की तरह एक अलग पदानुक्रम योजना चाहते हो सकता है:

Hibernate Single Table per Subclass

लाभ

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

नुकसान

  • पदानुक्रम विकसित होता है, यह खराब प्रदर्शन हो सकता है।
  • सबक्लास बनाने के लिए आवश्यक जॉइन की संख्या भी बढ़ती है।

Hibernate Single Table per Concrete class

लाभ

  • इस विरासत मानचित्रण का सबसे आसान तरीका लागू करने के लिए है।

नुकसान

  • डाटा thats अंतर्गत आता है करने के लिए एक माता पिता के वर्ग उपवर्ग तालिकाओं का एक संख्या है, जो ठोस वर्ग का प्रतिनिधित्व करता है में फैले है।
  • अधिकांश मामलों के लिए इस पदानुक्रम की अनुशंसा नहीं की जाती है।
  • एक माता पिता के वर्ग में किए गए परिवर्तन टेबल की बड़ी संख्या
  • एक क्वेरी माता पिता वर्ग के मामले में couched का चयन आपरेशन
  • की एक बड़ी संख्या कारण होने की संभावना है करने के लिए देखा जा सकता है

मैं एक के लिए आप सुझाव है सिंगल टेबल प्रति सबक्लास योजना देखें।हालांकि मुझे आपकी सटीक आवश्यकता के बारे में निश्चित नहीं है। लेकिन यह मदद कर सकता है।

+0

क्या आप बिल्कुल निश्चित हैं कि कुछ कस्टम deserializer लिखने का कोई तरीका नहीं है? मैं एक हाइबरनेट विशेषज्ञ नहीं हूं, लेकिन मैं शर्त लगाता हूं कि अगर हम हाइबरनेट को परिणामसेट को ऑब्जेक्ट में परिवर्तित करने के तरीके को देखते हैं, तो पीट के तरीके को अनुकूलित करने का एक तरीका है। –

+0

लिंक वायरलपेटेल के लिए धन्यवाद, अच्छा पढ़ा लेकिन दुर्भाग्य से यह वास्तव में मदद नहीं करता है। शायद यह सिर्फ एनोटेशन के साथ नहीं किया जा सकता है, जैसे लड़का मोग्राबी संकेत ...? – Pete

+0

हाय गाय, वैसे यह निश्चित है कि आप हाइबरनेट जैसे खुले ढांचे की कई डिफ़ॉल्ट कार्यक्षमताओं को ओवरराइड कर सकते हैं। लेकिन इस के साथ समस्या (तालिका प्रति पदानुक्रम) यह है कि आपका डेटा एकल तालिका में संग्रहीत है। और यह निर्धारित करने के लिए एक कॉलम होना चाहिए कि कौन सी डेटा पंक्ति पदानुक्रम में कक्षा से संबंधित है। –

7

मुझे पता है, यह एक बहुत पुराना सवाल है, लेकिन मुझे हाल ही में इस समस्या का सामना करना पड़ा और यह किसी के लिए उपयोगी साबित हो सकता है।

यह हाइबरनेट के @DiscriminatorFormula एनोटेशन का उपयोग करके किया जा सकता है। निम्नलिखित वर्णन Java Persistence with Hibernate, खंड 5.1.3 पर आधारित है; प्रासंगिकता का पेज पर पेज 202.

पर अंतिम अनुच्छेद @DiscriminatorFormula के साथ आप एक SQL बयान है कि discriminator के मूल्य को निर्धारित डेटाबेस से प्रासंगिक पंक्तियों को लाते समय प्रदान कर सकते हैं शुरू होता है। आपके मामले में, यह एक साधारण स्ट्रिंग होना चाहिए जो कुछ मनमाने ढंग से चयनित मूल्य का मूल्यांकन करे। इसके लिए काम करने के लिए, आपको उस नाम पर निर्णय लेने की आवश्यकता है जिसका उपयोग आपके Client इकाई के लिए किया जाएगा। मान लीजिए कि आप 'जेनेरिक क्लाइंट' को entity के नाम के रूप में चुनते हैं। यह वह नाम है जो @Entity एनोटेशन के भीतर name विशेषता के मान के रूप में दिखाई देना चाहिए। तो, पूरा उदाहरण, आपके मामले में निम्नलिखित की तरह दिखेगा।

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@Table(name = "client") 
@DiscriminatorFormula("'GenericClient'") // *1* 
public abstract class Client extends AbstractPersistable<Long> { 
    // ... 
} 

// Application A 
@Entity 
@DiscriminatorValue("GenericClient") // *2* 
public class SimpleClient extends Client { 
    // ... 
} 


// Application B 
@Entity 
@DiscriminatorValue("GenericClient") // *3* 
public class AdvancedClient extends Client { 
    // ... 
} 

लाइन है कि द्वारा '' निरूपित किया जाता है एसक्यूएल स्निपेट है, जो हमेशा वापस आ जाएगी 'GenericClient' अपने मूल्य के रूप में का एक हिस्सा है। Client के subclasses को हमेशा @DiscriminatorValue("GenericClient") के साथ एनोटेट किया जाना चाहिए। इसका अर्थ यह है कि जब हाइबरनेट डीबी से पंक्तियां प्राप्त करता है, तो ऑब्जेक्ट का निर्माण करने का प्रकार हमेशा Client का विशिष्ट उप-वर्ग होगा।

पैकेज जहां Client रहते उपवर्गों, और उपवर्गों के नाम तय कर रहे हैं:

उस मामले में, उपवर्गों पर @DiscriminatorValue("GenericClient") आवश्यकता नहीं होगी, आप सभी की जरूरत होगी करने के लिए है:

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@Table(name = "client") 
@DiscriminatorFormula("'com.example.fixed.path.FixedSubClassName'") 
public abstract class Client extends AbstractPersistable<Long> { 
    // ... 
} 

उप-वर्गों को किसी भी एनोटेशन की आवश्यकता नहीं होगी। discriminator-valueentity-name पर डिफ़ॉल्ट है, जो स्वयं पूरी तरह से योग्यता प्राप्त कक्षा-नाम के लिए डिफ़ॉल्ट है।

नोट:SQL बयान @DiscriminatorFormula() अंदर आपके लक्षित डीबी सर्वर के लिए कोई मान्य SQL बयान हो सकता है।

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