2010-09-03 11 views
6

पर प्रॉपर्टी नाम से प्रीपेड करने में असफल रहा है। मैं ManyToMany एसोसिएशन का उपयोग करके एक दूसरे को दो ऑब्जेक्ट्स मैप करने की कोशिश कर रहा हूं, लेकिन किसी कारण से जब मै मैप्डबी प्रॉपर्टी का उपयोग करता हूं, तो हाइबरनेट उलझन में प्रतीत होता है मैं वास्तव में क्या मैपिंग कर रहा हूँ के बारे में। यहां मेरी मैपिंग के बारे में एकमात्र अजीब चीज यह है कि एसोसिएशन किसी एक प्रविष्टि में प्राथमिक कुंजी फ़ील्ड पर नहीं किया जाता है (हालांकि फ़ील्ड अद्वितीय है)।हाइबरनेट कई प्रकार के योग्य वर्ग नाम को प्रॉपर्टी नाम पर कई टीओएमनी एसोसिएशन

तालिकाओं हैं:

Sequence (
    id NUMBER, 
    reference VARCHAR, 
) 

Project (
    id NUMBER 
) 

Sequence_Project (
    proj_id number references Project(id), 
    reference varchar references Sequence(reference) 
) 

वस्तुओं की तरह लग रहे (एनोटेशन थोड़ा गाढ़ा करने के लिए खेतों पर डाल, गेटर पर हैं):

class Sequence { 
    @Id 
    private int id; 

    private String reference; 

    @ManyToMany(mappedBy="sequences") 
    private List<Project> projects; 
} 

और मालिक पक्ष:

class Project { 
    @Id 
    private int id; 

    @ManyToMany 
    @JoinTable(name="sequence_project", 
       [email protected](name="id"), 
       [email protected](name="reference", 
            referencedColumnName="reference")) 
    private List<Sequence> sequences; 
} 

यह मैपिंग अपवाद के साथ विफल रहता है:

संपत्ति-रेफरी [_test_local_entities_Project_sequences] इकाई पर नहीं मिला [test.local.entities.Project]

यह अजीब तरह से पूरी तरह से योग्य वर्ग के नाम, अंडरस्कोर से विभाजित पहले जोड़ें करने लगता है। मैं इसे कैसे होने से बच सकता हूं?

संपादित करें: मैंने इसके साथ थोड़ा और खेला। थ्रो एक अलग अपवाद, mappedBy संपत्ति के नाम बदलने से अर्थात्:

org.hibernate.AnnotationException: test.local.entities.Project.sequences

तो: mappedBy एक अज्ञात लक्ष्य इकाई संपत्ति का संदर्भ एनोटेशन सही तरीके से प्रसंस्करण कर रहा है, लेकिन किसी भी तरह से संपत्ति संदर्भ सही ढंग से हाइबरनेट की आंतरिक कॉन्फ़िगरेशन में नहीं जोड़ा गया है।

+0

एक वर्ग की तरह लग सकता है, लेकिन परियोजना उस पर सार्वजनिक getSequences और सार्वजनिक setSequences है? – Affe

+0

@Affe मैं डबल चेक कर दूंगा, मुझे लगता है कि वर्तमान में यह सार्वजनिक/संरक्षित है। – wds

+0

बस मामले में, यदि आप 'अनुक्रम' संपत्ति का नाम किसी अन्य चीज़ में बदलते हैं तो क्या होता है उदा। 'Foo'? –

उत्तर

3

मैंने आपके प्रश्न द्वारा प्रस्तावित वही परिदृश्य किया है। और, जैसा कि अपेक्षित है, मुझे एक ही अपवाद मिलता है। पूरक कार्य के रूप में, मैंने एक ही परिदृश्य लेकिन को एक-से-कई-से-एक के साथ गैर-प्राथमिक कुंजी का उपयोग करके कॉलम जैसे संदर्भ के रूप में किया है। मैं अब मिल

SecondaryTable JoinColumn नहीं कर सकते संदर्भ एक गैर प्राथमिक एक बग कुंजी

खैर, यह हो सकता है ??? खैर, हाँ (और आपका कामकाज ठीक काम करता है (+1))। यदि आप प्राथमिक कुंजी के रूप में गैर-प्राथमिक कुंजी का उपयोग करना चाहते हैं, तो आपको यह सुनिश्चित करना होगा कि यह अद्वितीय है। शायद यह बताता है कि क्यों हाइबरनेट प्राथमिक कुंजी के रूप में गैर-प्राथमिक कुंजी का उपयोग करने की अनुमति नहीं देता है (अनजान उपयोगकर्ताओं को अप्रत्याशित व्यवहार मिल सकते हैं)।

आप एक ही मानचित्रण का उपयोग करना चाहते हैं, तो आप @ OneToMany-ManyToOne में अपने @ManyToMany संबंध विभाजित कर सकते हैं कैप्सूलीकरण का उपयोग करके आप अपने में शामिल हो गए वर्ग के बारे में चिंता करने की जरूरत नहीं

परियोजना

@Entity 
public class Project implements Serializable { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    @OneToMany(mappedBy="project") 
    private List<ProjectSequence> projectSequenceList = new ArrayList<ProjectSequence>(); 

    @Transient 
    private List<Sequence> sequenceList = null; 

    // getters and setters 

    public void addSequence(Sequence sequence) { 
     projectSequenceList.add(new ProjectSequence(new ProjectSequence.ProjectSequenceId(id, sequence.getReference()))); 
    } 

    public List<Sequence> getSequenceList() { 
     if(sequenceList != null) 
      return sequenceList; 

     sequenceList = new ArrayList<Sequence>(); 
     for (ProjectSequence projectSequence : projectSequenceList) 
      sequenceList.add(projectSequence.getSequence()); 

     return sequenceList; 
    } 

} 

अनुक्रम

@Entity 
public class Sequence implements Serializable { 

    @Id 
    private Integer id; 
    private String reference; 

    @OneToMany(mappedBy="sequence") 
    private List<ProjectSequence> projectSequenceList = new ArrayList<ProjectSequence>(); 

    @Transient 
    private List<Project> projectList = null; 

    // getters and setters 

    public void addProject(Project project) { 
     projectSequenceList.add(new ProjectSequence(new ProjectSequence.ProjectSequenceId(project.getId(), reference))); 
    } 

    public List<Project> getProjectList() { 
     if(projectList != null) 
      return projectList; 

     projectList = new ArrayList<Project>(); 
     for (ProjectSequence projectSequence : projectSequenceList) 
      projectList.add(projectSequence.getProject()); 

     return projectList; 
    } 

} 

ProjectSequence

@Entity 
public class ProjectSequence { 

    @EmbeddedId 
    private ProjectSequenceId projectSequenceId; 

    @ManyToOne 
    @JoinColumn(name="ID", insertable=false, updatable=false) 
    private Project project; 

    @ManyToOne 
    @JoinColumn(name="REFERENCE", referencedColumnName="REFERENCE", insertable=false, updatable=false) 
    private Sequence sequence; 

    public ProjectSequence() {} 
    public ProjectSequence(ProjectSequenceId projectSequenceId) { 
     this.projectSequenceId = projectSequenceId; 
    } 

    // getters and setters 

    @Embeddable 
    public static class ProjectSequenceId implements Serializable { 

     @Column(name="ID", updatable=false) 
     private Integer projectId; 

     @Column(name="REFERENCE", updatable=false) 
     private String reference; 

     public ProjectSequenceId() {} 
     public ProjectSequenceId(Integer projectId, String reference) { 
      this.projectId = projectId; 
      this.reference = reference; 
     } 

     @Override 
     public boolean equals(Object o) { 
      if (!(o instanceof ProjectSequenceId)) 
       return false; 

      final ProjectSequenceId other = (ProjectSequenceId) o; 
      return new EqualsBuilder().append(getProjectId(), other.getProjectId()) 
             .append(getReference(), other.getReference()) 
             .isEquals(); 
     } 

     @Override 
     public int hashCode() { 
      return new HashCodeBuilder().append(getProjectId()) 
             .append(getReference()) 
             .hashCode(); 
     } 

    } 

} 
+0

वास्तव में वही है जो मैंने किया था। मैं इसे स्वीकार कर रहा हूं क्योंकि कोड दूसरों की मदद कर सकता है। :-) – wds

+0

@wds धन्यवाद! मुझे उम्मीद है कि यह उपयोगी हो सकता है –

2

मैंने आखिरकार इसे कम या ज्यादा समझ लिया। मुझे लगता है कि यह मूल रूप से एक हाइबरनेट बग है।

संपादित करें: मैं संघ के मालिक पक्ष बदलकर इसे ठीक करने की कोशिश की:

class Sequence { 
    @Id 
    private int id; 

    private String reference; 

    @ManyToMany 
    @JoinTable(name="sequence_project", 
      [email protected](name="id"), 
      [email protected](name="reference", 
         referencedColumnName="reference")) 
    private List<Project> projects; 
} 

class Project { 
    @Id 
    private int id; 

    @ManyToMany(mappedBy="projects") 
    private List<Sequence> sequences; 
} 

यह काम किया लेकिन समस्याओं कहीं और की वजह से (टिप्पणी देखें)। इसलिए मैंने अनुक्रम और परियोजना में कई से एक संगठनों के साथ एक इकाई के रूप में एसोसिएशन को छोड़ दिया और मॉडलिंग किया। मुझे लगता है कि यह कम से कम एक दस्तावेज/गलती हैंडलिंग बग पर है (अपवाद बहुत प्रासंगिक नहीं है, और विफलता मोड सिर्फ गलत है) और इसे हाइबरनेट देवों को रिपोर्ट करने का प्रयास करेगा।

+0

आगे की परीक्षा से पता चला कि यह काम नहीं करता है, क्योंकि अब हाइबरनेट इकाई के आईडी कॉलम के साथ एसोसिएशन टेबल में स्ट्रिंग कॉलम में शामिल होने का प्रयास कर रहा है। ऐसा लगता है कि ऐसा करना असंभव है, किसी भी तरह। – wds

0

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

हमारे पास एक परियोजना में आपके जैसा ही मुद्दा था जहां हम विरासत डेटाबेस स्कीमा भी नहीं बदल सके। हाइबरनेट को डंप करने और MyBatis (http://www.mybatis.org) का उपयोग करने का एकमात्र व्यवहार्य विकल्प था, जहां आपके पास अधिक जटिल जुड़ने की स्थितियों को व्यक्त करने के लिए मूल एसक्यूएल की पूर्ण लचीलापन है।

+0

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

0

मैं एक दर्जन बार अब इस समस्या में चलाने के लिए और केवल वैकल्पिक हल मैंने पाया संबंध के दूसरे पक्ष पर बदली कॉलम के साथ दो बार @JoinTable के विन्यास कर रहा है:

class Sequence { 

    @Id 
    private int id; 

    private String reference; 

    @ManyToMany 
    @JoinTable(
     name = "sequence_project", 
     joinColumns = @JoinColumn(name="reference", referencedColumnName="reference"), 
     inverseJoinColumns = @JoinColumn(name="id") 
    ) 
    private List<Project> projects; 

} 

class Project { 

    @Id 
    private int id; 

    @ManyToMany 
    @JoinTable(
     name = "sequence_project", 
     joinColumns = @JoinColumn(name="id"), 
     inverseJoinColumns = @JoinColumn(name="reference", referencedColumnName="reference") 
    ) 
    private List<Sequence> sequences; 

} 

मैं अभी तक की कोशिश की नहीं किया यह प्राथमिक कुंजी से अलग कॉलम के साथ।

+0

आप दो यूनिडायरेक्शनल कई से कई संगठनों को परिभाषित कर रहे हैं, यह अर्थात् बहुत अलग है (और मुझे यह भी यकीन नहीं है कि सब ठीक से काम करेगा)। –

+0

वे वास्तव में एक संबंध हैं क्योंकि मैं एक ही जॉइन टेबल का उपयोग करता हूं और समान कॉलम (बस स्विच) में शामिल होता हूं। – whiskeysierra

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