2010-11-20 20 views
7

मैं एक मेज दोनों विदेशी कुंजी साथ दो अलग-अलग तालिकाओं के लिए दो विदेशी कुंजी है कि एक स्तंभ साझा करने की है:क्या हाइबरनेट विदेशी कुंजी ओवरलैप करने में सक्षम होना चाहिए?

CREATE TABLE ZipAreas 
(
    country_code CHAR(2) NOT NULL, 
    zip_code VARCHAR(10) NOT NULL, 
    state_code VARCHAR(5) NOT NULL, 
    city_name VARCHAR(100) NOT NULL, 
    PRIMARY KEY (country_code, zip_code, state_code, city_name), 
    FOREIGN KEY (country_code, zip_code) REFERENCES Zips (country_code, code), 
    FOREIGN KEY (country_code, state_code, city_name) REFERENCES Cities (country_code, state_code, name) 
) 

जैसा कि आप देख सकते हैं, वहाँ साझा करने COUNTRY_CODE (संयोग से उसी स्तंभ को संदर्भित दो FKS हैं रेफरेंसिएशन पथ का अंत)। इकाई वर्ग (जेपीए 1.0 @IdClass) की तरह दिखता है:

@Entity 
@Table(name = "ZipAreas") 
@IdClass(value = ZipAreaId.class) 
public class ZipArea implements Serializable 
{ 
    @Id 
    @Column(name = "country_code", insertable = false, updatable = false) 
    private String countryCode; 

    @Id 
    @Column(name = "zip_code", insertable = false, updatable = false) 
    private String zipCode; 

    @Id 
    @Column(name = "state_code", insertable = false, updatable = false) 
    private String stateCode; 

    @Id 
    @Column(name = "city_name", insertable = false, updatable = false) 
    private String cityName; 

    @ManyToOne 
    @JoinColumns(value = {@JoinColumn(name = "country_code", referencedColumnName = "country_code"), @JoinColumn(name = "zip_code", referencedColumnName = "code")}) 
    private Zip zip = null; 

    @ManyToOne 
    @JoinColumns(value = {@JoinColumn(name = "country_code", referencedColumnName = "country_code", insertable = false, updatable = false), @JoinColumn(name = "state_code", referencedColumnName = "state_code"), @JoinColumn(name = "city_name", referencedColumnName = "name")}) 
    private City city = null; 

    ... 
} 

आप देख सकते हैं मैं countryCode संपत्ति और केवल पढ़ने के लिए जैसे शहर के COUNTRY_CODE @JoinColumn चिह्नित किये (insertable = false, updatable = false)। हाइबरनेट इस कहने में विफल रहता है:

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: geoinfo] Unable to configure EntityManagerFactory 
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:374) 
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:56) 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48) 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32) 
    at tld.geoinfo.Main.main(Main.java:27) 
Caused by: org.hibernate.AnnotationException: Mixing insertable and non insertable columns in a property is not allowed: tld.geoinfo.model.ZipAreacity 
    at org.hibernate.cfg.Ejb3Column.checkPropertyConsistency(Ejb3Column.java:563) 
    at org.hibernate.cfg.AnnotationBinder.bindManyToOne(AnnotationBinder.java:2703) 
    at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1600) 
    at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:796) 
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:707) 
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3977) 
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3931) 
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1368) 
    at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345) 
    at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1477) 
    at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193) 
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1096) 
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:278) 
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:362) 
    ... 4 more 

यह ईमानदारी से मेरे लिए बहुत बुनियादी दिखता है। "किसी संपत्ति में डालने योग्य और गैर डालने योग्य कॉलम को मिक्स करने की अनुमति नहीं है" यह इतना कमजोर "बहाना है" है ना?

क्या हाइबरनेट इसे संभालने में सक्षम होना चाहिए, उदा। जेपीए spec के अनुसार? क्या यह एक बग है?

+0

यहाँ एक JavaSE, HSQLDB, चींटी स्टैंडअलोन ऐप्स: http://www.kawoolutions.com/media/geoinfo-hib-overlapping -fks.zip – Kawu

+0

हाइबरनेट समग्र प्राथमिक कुंजी को नापसंद करता है - कुछ स्थितियों में यह गड़बड़ हो जाता है। सिंगल कॉलम प्राथमिक कुंजी का उपयोग करने के लिए अपने डेटाबेस को दोबारा करने का प्रयास करें। –

+0

हाँ हाइबरनेट समग्र कुंजी पर बेकार है। किसी भी मामले में, इसकी सूचना कभी नहीं मिली है, अब यह है: http: //opensource.atlassian।कॉम/प्रोजेक्ट/हाइबरनेट/ब्राउज/एचएचएच -6221 – Kawu

उत्तर

9

हाइबरनेट 5 के साथ समर्थित किया जाएगा, देख https://hibernate.atlassian.net/browse/HHH-6221

+2

ऐसा लगता है कि इसे हाइबरनेट 6 में स्थानांतरित कर दिया गया है। –

+0

यहां हाइबरनेट एटलसियन मुद्दों पृष्ठ पर समस्या है: https://hibernate.atlassian.net/browse/HHH-6221 – Ben

18

सत्यापन बाईपास और यह काम करने के लिए प्राप्त करने के लिए, इस प्रकार का संकेत स्तंभ एक "@JoinColumnsOrFormulas" तो समाधान कर दिया है एक तरीका होता है:

त्रुटि:

@ManyToOne 
@JoinColumns(value = { 
    @JoinColumn(name = "country_code", referencedColumnName = "country_code"), 
    @JoinColumn(name = "zip_code", referencedColumnName = "code")}) 
private Zip zip = null; 

@ManyToOne 
@JoinColumns(value = { 
    @JoinColumn(name = "country_code", referencedColumnName = "country_code", insertable = false, updatable = false), 
    @JoinColumn(name = "state_code", referencedColumnName = "state_code"), 
    @JoinColumn(name = "city_name", referencedColumnName = "name")}) 
private City city = null; 

ठीक:

@ManyToOne 
@JoinColumns(value = { 
    @JoinColumn(name = "country_code", referencedColumnName = "country_code"), 
    @JoinColumn(name = "zip_code", referencedColumnName = "code")}) 
private Zip zip = null; 

@ManyToOne 
@JoinColumnsOrFormulas(value = { 
    @JoinColumnOrFormula(formula = @JoinFormula(value = "country_code", referencedColumnName = "country_code")), 
    @JoinColumnOrFormula(column = @JoinColumn(name = "state_code", referencedColumnName = "state_code")), 
    @JoinColumnOrFormula(column = @JoinColumn(name = "city_name", referencedColumnName = "name")) 
}) 
private City city = null; 

सम्मान,

+6

मेरा मानना ​​है कि यह स्वीकार कर लिया जवाब होना चाहिए, क्योंकि यह भविष्य में कहीं न कहीं अभी और नहीं एक काम कर समाधान प्रदान करता है जब हाइबरनेट 5 जीए है। – azerole

+0

@ManuNavarro खराब नमूने की तुलना में अच्छे नमूने पर शहर की संपत्ति के और कॉलम क्यों हैं? – banterCZ

+0

हैलो @banterCZ, बाईं ओर ले जाता है और तीसरे संबंध –

0

मैं हाइबरनेट 5 का उपयोग कर रहा हूं और मुझे अभी भी यह अपवाद मिलता है। यदि आप डालने = "झूठी", अद्यतन = "झूठी" केवल एक को जोड़ते हैं, तो आपको एक अपवाद मिलेगा जिसमें कहा गया है कि आप मिश्रित और गैर-सम्मिलित कॉलम मिश्रित करते हैं और इसकी अनुमति नहीं है। यह एक मुद्दा है जो पहले से ही ट्रैकर में है, लेकिन ऐसा हल नहीं किया जा रहा है। Hibernate throws AnnotationException on column used by multiple overlapping foreign keys

हमारे मामले में, यह है कि हम EclipseLink है, जो वास्तव में बहुत आसान है कि आप मुख्य रूप से persistence.xml की जगह और JPQL को HSQL (हाइबरनेट एसक्यूएल) (जेपीए एसक्यूएल) को फिर से लिखने की जरूरत को देखते हुए के लिए चले थे। इसके अलावा आपको कस्टम नामकरण रणनीतियों को प्रतिस्थापित करने की आवश्यकता हो सकती है (ग्रहण उन्हें सत्र कस्टमाइज़र कहते हैं)। निस्संदेह यह करना कठिन हो सकता है यदि आप हाइबरनेट की विशेष विशेषताओं जैसे कि हाइबरनेट खोज आदि का उपयोग करते हैं। लेकिन हमारे मामले में, हमने सप्ताहों के लिए ओवरलैपिंग विदेशी कुंजी को ठीक करने का प्रयास किया, जब माइग्रेशन ने अंत में केवल घंटों का समय लिया।

0

यह अभी भी हाइबरनेट 5 में हल नहीं हुआ है। हालांकि, अगर मैं @JoinColumnsOrFormulas का उपयोग करता हूं तो मुझे ClassCastException मिलता है। जोड़ सब में शामिल होने के स्तंभों मेरी समस्या हल पर insertable = false, updatable = false:

उदाहरण:

@ManyToOne 
@JoinColumns(value = { 
    @JoinColumn(name = "country_code", referencedColumnName = "country_code", insertable = false, updatable = false), 
    @JoinColumn(name = "state_code", referencedColumnName = "state_code", insertable = false, updatable = false), 
    @JoinColumn(name = "city_name", referencedColumnName = "name", insertable = false, updatable = false)}) 
private City city = null;