2009-04-24 11 views
59

मैं एक एक-से-एक रिश्ता है लेकिन hibernatetool शिकायत जब स्कीमा पैदा होता है। यहाँ एक उदाहरण है कि समस्या से पता चलता है:जेपीए हाइबरनेट एक-से-एक संबंध

@Entity 
public class Person { 
    @Id 
    public int id; 

    @OneToOne 
    public OtherInfo otherInfo; 

    rest of attributes ... 
} 

व्यक्ति OtherInfo के साथ एक-से-एक संबंध नहीं है:

@Entity 
public class OtherInfo { 
    @Id 
    @OneToOne(mappedBy="otherInfo") 
    public Person person; 

    rest of attributes ... 
} 

व्यक्ति OtherInfo के किनारे के मालिक है। अन्य इंफो एक स्वामित्व वाली पक्ष है इसलिए व्यक्ति व्यक्ति में विशेषता नाम "अन्य इंफो" निर्दिष्ट करने के लिए mappedBy का उपयोग करता है।

org.hibernate.MappingException: Could not determine type for: Person, at table: OtherInfo, for columns: [org.hibernate.mapping.Column(person)] 
     at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:292) 
     at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.java:175) 
     at org.hibernate.cfg.Configuration.iterateGenerators(Configuration.java:743) 
     at org.hibernate.cfg.Configuration.generateDropSchemaScript(Configuration.java:854) 
     at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:128) 
     ... 

किसी भी विचार क्यों:

मैं जब hibernatetool का उपयोग कर डेटाबेस स्कीमा उत्पन्न करने के लिए निम्न त्रुटि मिल सकता है? क्या मैं कुछ गलत कर रहा हूं या यह एक हाइबरनेट बग है?

उत्तर

85

जेपीए एक OneToOne या ManyToOne मानचित्रण पर @Id एनोटेशन अनुमति नहीं है। आपको क्या करने की कोशिश कर रहे हैं साझा प्राथमिक कुंजी साथ एक-से-एक इकाई संघ है। सरलतम मामले दिशाहीन है एक-से-एक साझा कुंजी के साथ:

@Entity 
public class Person { 
    @Id 
    private int id; 

    @OneToOne 
    @PrimaryKeyJoinColumn 
    private OtherInfo otherInfo; 

    rest of attributes ... 
} 

इस के साथ मुख्य समस्या यह है कि जेपीए OtherInfo इकाई में साझा प्राथमिक कुंजी पीढ़ी के लिए कोई समर्थन प्रदान करता है।

@Entity 
public class OtherInfo { 
    @Id @GeneratedValue(generator = "customForeignGenerator") 
    @org.hibernate.annotations.GenericGenerator(
     name = "customForeignGenerator", 
     strategy = "foreign", 
     parameters = @Parameter(name = "property", value = "person") 
    ) 
    private Long id; 

    @OneToOne(mappedBy="otherInfo") 
    @PrimaryKeyJoinColumn 
    public Person person; 

    rest of attributes ... 
} 

इसके अलावा, here देखें: क्लासिक किताब Java Persistence with Hibernate by Bauer and King हाइबरनेट एक्सटेंशन का उपयोग कर समस्या के लिए निम्न समाधान देता है।

+3

महान जवाब, बस जोड़ने के लिए है कि आप अपने व्यक्ति वर्ग में निम्नलिखित टिप्पणी जोड़ने के लिए और साथ ही आवश्यकता हो सकती है चाहता था (मैं सही ढंग से काम कराने के लिए किया था): '@Cascade ({CascadeType.ALL, CascadeType। DELETE_ORPHAN}) ' –

+0

धन्यवाद, इससे मेरी समस्या पर मदद मिली .. क्या आप जानते हैं कि वैसे भी केवल जेपीए एनोटेशन का उपयोग करें और हाइबरनेट से बचें? – Elton

+0

@ एल्टन - यदि कोई तरीका है तो यह जेपीए 2.0 में होना चाहिए - हालांकि मैंने इसे नहीं देखा। – topchef

1

मुझे यकीन है कि आप हाइबरनेट में एक आईडी/PrimaryKey के रूप में एक रिश्ते का उपयोग कर सकते नहीं कर रहा हूँ।

1

इस

@Entity 

@Table(name="tblperson") 

public class Person { 

public int id; 

public OtherInfo otherInfo; 
@Id //Here Id is autogenerated 
@Column(name="id") 
@GeneratedValue(strategy=GenerationType.AUTO) 
public int getId() { 
    return id; 
} 
public void setId(int id) { 
    this.id = id; 
} 

@OneToOne(cascade = CascadeType.ALL,targetEntity=OtherInfo.class) 
@JoinColumn(name="otherInfo_id") //there should be a column otherInfo_id in Person 
public OtherInfo getOtherInfo() { 
    return otherInfo; 
} 
public void setOtherInfo(OtherInfo otherInfo) { 
    this.otherInfo= otherInfo; 
} 
rest of attributes ... 
} 


@Entity 

@Table(name="tblotherInfo") 

public class OtherInfo { 

private int id; 

private Person person; 

@Id 

@Column(name="id") 
@GeneratedValue(strategy=GenerationType.AUTO) 
public Long getId() { 
    return id; 
} 
public void setId(Long id) { 
    this.id = id; 
} 

    @OneToOne(mappedBy="OtherInfo",targetEntity=Person.class) 
public College getPerson() { 
    return person; 
} 
public void setPerson(Person person) { 
    this.person = person; 
}  
rest of attributes ... 
} 
4

मुझे लगता है कि आप अभी भी OtherInfo कक्षा में प्राथमिक कुंजी संपत्ति की जरूरत है की कोशिश करो।

@Entity 
public class OtherInfo { 
    @Id 
    public int id; 

    @OneToOne(mappedBy="otherInfo") 
    public Person person; 

    rest of attributes ... 
} 

इसके अलावा, आपको मैपिंग के दूसरी तरफ @PrimaryKeyJoinColumn एनोटेशन जोड़ने की आवश्यकता हो सकती है। मुझे पता है कि हाइबरनेट डिफ़ॉल्ट रूप से इसका उपयोग करता है। लेकिन फिर मैंने जेपीए एनोटेशन का उपयोग नहीं किया है, जो आपको यह निर्दिष्ट करने की आवश्यकता है कि एसोसिएशन कैसे काम करता है।

2

मैं ऐसा करने का एक बेहतर तरीका हो:

@Entity 
public class Person { 

    @OneToOne(cascade={javax.persistence.CascadeType.ALL}) 
    @JoinColumn(name = "`Id_OtherInfo`") 
    public OtherInfo getOtherInfo() { 
     return otherInfo; 
    } 

} 

बस इतना ही

+0

इसके अलावा स्वामित्व वाली तरफ, यानी जिस पक्ष में विदेशी कुंजी है, उसे धारावाहिक लागू करना चाहिए (हाइबरेट 4/जेपीए 2 के साथ) –

22

यह भी हाइबरनेट के GenericGenerator के बजाय जेपीए 2.0 @MapsId एनोटेशन का उपयोग कर काम करना चाहिए:

@Entity 
public class Person { 

    @Id 
    @GeneratedValue 
    public int id; 

    @OneToOne 
    @PrimaryKeyJoinColumn 
    public OtherInfo otherInfo; 

    rest of attributes ... 
} 

@Entity 
public class OtherInfo { 

    @Id 
    public int id; 

    @MapsId 
    @OneToOne 
    @JoinColumn(name="id") 
    public Person person; 

    rest of attributes ... 
} 

अधिक धारा 5.1.2.2.7 के तहत हाइबरनेट 4.1 दस्तावेज़ में इस पर विवरण।

+1

[आलसी के लिए लिंक] (https://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/# d5e2666)। मैंने वनटोन क्लास पर आईडी आईडी एनोटेशन का उपयोग करना चुना है (आपके उदाहरण में अन्य इंफो), लेकिन यह केवल एक बच्चे-अभिभावक परिदृश्य में काम करता है। जवाब के लिए धन्यवाद! – Joe

+2

आपने 'प्राथमिकKeyJoinColumn' का उपयोग करने के बजाय' अन्य इंफो 'पर '@ JoinColumn' क्यों निर्दिष्ट किया? –

10

तुम बस @JoinColumn(name="column_name") जोड़ने के लिए इकाई संबंध मेजबान की जरूरत है। कॉलम_नाम व्यक्तिगत तालिका में डेटाबेस कॉलम नाम है। mappedBy = "var_name" var_name व्यक्ति वर्ग में otherInfo के लिए चर नाम है:

@Entity 
public class Person { 
    @Id 
    public int id; 

    @OneToOne 
    @JoinColumn(name="other_info") 
    public OtherInfo otherInfo; 

    rest of attributes ... 
} 

व्यक्ति OtherInfo के साथ एक-से-एक संबंध नहीं है।

@Entity 
public class OtherInfo { 
    @Id 
    @OneToOne(mappedBy="otherInfo") 
    public Person person; 

    rest of attributes ... 
} 
संबंधित मुद्दे