2010-04-12 15 views
6

मैं अनुभव हासिल करने के लिए हाइबरनेट के साथ प्रयोग कर रहा हूं। Student और Worker:हाइबरनेट: उप-वर्ग में इस मैपिंग के साथ क्या गलत है विदेशी कुंजी पर शामिल हो गए?

public abstract class Person { 
    private Long id; 
    ... 
} 

public class Student extends Person { ... } 

एक अन्य वर्ग, Employer, Worker के साथ एक द्विदिश एक-से-कई संबंध नहीं है मैं दो उपवर्गों के साथ एक कक्षा Person बनाया।

public class Worker extends Person { 
    private Employer employer; 
    ... 
} 

public class Employer { 
    private String taxId; 
    private Set<Worker> employees = new HashSet<Worker>(); 
    ... 
} 

जिसके लिए मानचित्रण

<class name="Employer" table="EMPLOYER"> 
    <id name="taxId" column="TAX_ID" length="11"> 
     <generator class="assigned"/> 
    </id> 
    ... 
    <set name="employees" inverse="true"> 
     <key column="EMPLOYER_TAX_ID"/> 
     <one-to-many class="Worker"/> 
    </set> 
</class> 

वंशानुगत पदानुक्रम एक मिश्रित रणनीति, जहां StudentPERSON मेज पर मैप किया गया है के साथ मॉडलिंग की है, लेकिन Worker अपनी ही तालिका में संग्रहीत किया जाता है, एक साथ शामिल हो गए विदेशी कुंजी:

<class name="Person" table="PERSON"> 
    <id name="id" column="PERSON_ID" type="long" unsaved-value="0"> 
     <generator class="native"/> 
    </id> 
    <discriminator column="PERSON_TYPE" type="string"/> 
    ... 
    <subclass name="Student" discriminator-value="STU"> ... </subclass> 

    <subclass name="Worker" discriminator-value="WRK"> 
     <join table="WORKER"> 
      <key column="WORKER_ID"/> 
      <many-to-one name="employer" column="EMPLOYER_TAX_ID" cascade="save-update"/> 
      ... 
     </join> 
    </subclass> 
</class> 

मैं अपाचे डर्बी 10.5.3.0 का उपयोग करें औरकी स्थापना करके स्कीमा autogenerate 0 से create-drop

यह सब परीक्षण करने के लिए, मैं निम्नलिखित डाटासेट के साथ एक DBUnit परीक्षण बनाया:

<EMPLOYER TAX_ID   = "1234567890" 
      ... 
/> 
<PERSON PERSON_ID   = "12345" 
      PERSON_TYPE  = "WRK" 
      ... 
/> 
<WORKER WORKER_ID   = "12345" 
      EMPLOYER_TAX_ID = "1234567890" 
      ... 
/> 

मैं एक परीक्षण है जो कार्यकर्ता इकाई को लोड करता है और यह सत्यापित करें कि वह सही कर्मचारी है कि है। यह गुजरता है तो विपरीत दिशा के लिए एक परीक्षण:

String taxId = "1234567890"; 

    Employer employer = (Employer) session.get(Employer.class, taxId); 

    assertNotNull(employer); 
    assertThat(employer.getEmployees().size(), is(1)); 

निष्पादन पर, पिछले ज़ोर विफल रहता है क्योंकि कर्मचारियों के सेट खाली है।

गहरी खुदाई, मैंने पाया कि किसी कारण के लिए हाइबरनेट के लिए तालिका व्यक्ति में बजाय कार्यकर्ता का लग रहा है (और बनाता है) EMPLOYER_TAX_ID स्तंभ! यह वर्कर में भी मौजूद है, लेकिन उस प्रश्न में इसका उपयोग नहीं किया जाता है। कर्मचारियों के सेट को पॉप्युलेट करने के लिए चुनिंदा बयान है:

select 
    employees0_.EMPLOYER_TAX_ID as EMPLOYER10_1_, 
    employees0_.PERSON_ID as PERSON1_1_, 
    employees0_.PERSON_ID as PERSON1_1_0_, 
    employees0_.FIRST_NAME as FIRST3_1_0_, 
    employees0_.FAMILY_NAME as FAMILY4_1_0_, 
    employees0_.DATE_OF_BIRTH as DATE5_1_0_, 
    employees0_.HOME_ADDRESS as HOME6_1_0_, 
    employees0_.CITY as CITY1_0_, 
    employees0_.ZIP as ZIP1_0_, 
    employees0_1_.EMPLOYER_TAX_ID as EMPLOYER2_2_0_, 
    employees0_1_.JOB_TITLE as JOB3_2_0_, 
    employees0_1_.JOB_GRADE as JOB4_2_0_, 
    employees0_1_.START_DATE as START5_2_0_ 
from 
    PERSON employees0_ 
inner join 
    WORKER employees0_1_ 
     on employees0_.PERSON_ID=employees0_1_.WORKER_ID 
where 
    employees0_.EMPLOYER_TAX_ID=? 

यह क्यों है? और मैं वर्कर तालिका में EMPLOYER_TAX_ID को हाइबरनेट कैसे ढूंढ सकता हूं?

ध्यान दें कि चूंकि यह एक प्रयोगात्मक प्रोजेक्ट है, इसलिए मैं बस कुछ भी बदल सकता हूं। मैं किसी भी कामकाज की सराहना करता हूं, लेकिन मैं यह समझना पसंद करूंगा कि क्या हो रहा है और इस मैपिंग को ठीक कर रहा है (जितना संभव हो)।

अद्यतन: यदि मैं एक साफ <joined-subclass> विरासत मैपिंग रणनीति पर स्विच करता हूं, तो जेनरेट की गई स्कीमा दिखती है और परीक्षण पास हो जाता है। यह एक अच्छा कामकाज है, लेकिन मैं अभी भी उत्सुक हूं कि मिश्रित रणनीति को सही तरीके से काम करने का कोई तरीका है या नहीं।

+0

यदि आप जेपीए एनोटेशन का उपयोग कर सकते हैं तो अभी भी उन ग़लत XML फ़ाइल का उपयोग क्यों करें? – Kdeveloper

+0

@Kdeveloper हमारी वास्तविक परियोजना एक्सएमएल का उपयोग करती है, इसलिए यह मेरा मुख्य लक्ष्य है जिसका प्रयोग करना है। लेकिन मैं भविष्य में एनोटेशन के लिए अपनी पालतू परियोजना का विस्तार करूंगा, क्योंकि समय की अनुमति देता है ... –

+1

बस बाद के संदर्भ के लिए, एक से कई बिडरेक्शनल रिलेशनशिप एनोटेशन का उपयोग करके परिभाषित किया जाएगा: '@OneToMany (mappedBy =" nameOfSingleInstanceInOtherEntity ")' \t '@ManyToOne @JoinColumn (name =" nameWhichYouWishToGiveToIdField ")' –

उत्तर

2

यह लगता है कि ज्ञात बग: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1015

यह उम्र के बाद से जाना जाता है और समय की टन सूचना दी गई है। फिर भी, वे इसे ठीक नहीं कर रहे हैं ...

+0

वैसे, के साथ समस्या यह है कि इसका परिणाम विशाल प्रश्न दो उप-वर्गों के साथ इतना बड़ा नहीं है, लेकिन प्रत्येक अगला उपclass एसक्यूएल आकार में काफी जोड़ता है। – doublep

+0

धन्यवाद, यह वास्तव में एक ही मामला प्रतीत होता है! –

0

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

<joined-subclass name="Worker" table="WORKER"> 
    <key column="WORKER_ID"/> 
    <many-to-one name="employer" column="EMPLOYER_TAX_ID" cascade="save-update"/> 
    ... 
</joined-subclass> 

आशा इस मदद करता है।

+0

एक जुड़े सबक्लास का उपयोग करने का तात्पर्य है कि किसी अन्य अंतर्निहित रणनीति का उपयोग करने का कोई तरीका नहीं है। शायद वहां [ऐसा करने का कोई मौका नहीं है] (http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/inheritance.html#inheritance-mixing-tableperclass-tablepersubclass)। –