2010-04-06 14 views
152

इन उदाहरणों में TopLink JPA Annotation Reference पर:एक द्विपक्षीय जेपीए वनटोनी/मनीटोन एसोसिएशन में, "एसोसिएशन के विपरीत पक्ष" का क्या अर्थ है?

उदाहरण 1-59 @OneToMany - ग्राहक वर्ग जेनेरिक्स के साथ

@Entity 
public class Customer implements Serializable { 
    ... 
    @OneToMany(cascade=ALL, mappedBy="customer") 
    public Set<Order> getOrders() { 
     return orders; 
    } 
    ... 
} 

उदाहरण 1-60 @ManyToOne - आदेश कक्षा जेनेरिक्स साथ

@Entity 
public class Order implements Serializable { 
    ... 
    @ManyToOne 
    @JoinColumn(name="CUST_ID", nullable=false) 
    public Customer getCustomer() { 
     return customer; 
    } 
    ... 
} 

ऐसा लगता है कि Customer इकाई एसोसिएशन का मालिक है। हालांकि, एक ही दस्तावेज़ में mappedBy विशेषता के लिए विवरण में लिखा है कि:

अगर रिश्ते द्विदिश है, तो mappedBy तत्व की उलटा (गैर मालिक) की ओर सेट क्षेत्र या संपत्ति के संबंध में संबंध उदाहरण 1-60 शो के रूप में संबंध है।

हालांकि, अगर मैं गलत नहीं हूँ, यह उदाहरण की तरह, लगता है mappedBy वास्तव में, संघ के मालिक की ओर निर्दिष्ट किया जाता है बल्कि गैर मालिक पक्ष की तुलना में।

तो मेरे सवाल का मूल रूप से है:

  1. द्विदिश में (एक-से-कई/कई-से-एक) संघ, संस्थाओं की जो मालिक है? हम एक तरफ मालिक के रूप में कैसे नामित कर सकते हैं? हम मालिक के रूप में कई पक्षों को कैसे नामित कर सकते हैं?

  2. "एसोसिएशन के विपरीत पक्ष" का क्या अर्थ है? हम एक पक्ष को विपरीत के रूप में कैसे नामित कर सकते हैं? हम कई पक्षों को विपरीत के रूप में कैसे नामित कर सकते हैं?

+1

आपके द्वारा प्रदान किया गया लिंक पुराना है। कृपया अद्यतन करें। – MartinL

उत्तर

274

इसे समझने के लिए, आपको एक कदम वापस लेना होगा। ओओ में, ग्राहक ऑर्डर का मालिक है (ऑर्डर ग्राहक ऑब्जेक्ट में एक सूची है)। ग्राहक के बिना आदेश नहीं हो सकता है। तो ग्राहक आदेश के मालिक प्रतीत होता है।

लेकिन एसक्यूएल दुनिया में, एक आइटम में वास्तव में दूसरे के लिए एक सूचक होगा। चूंकि एन ऑर्डर के लिए 1 ग्राहक है, इसलिए प्रत्येक ऑर्डर में उस ग्राहक के लिए एक विदेशी कुंजी होती है जिसका वह संबंधित है। यह "कनेक्शन" है और इसका मतलब है कि कनेक्शन (जानकारी) "(या शाब्दिक रूप से) है। यह ओओ/मॉडल दुनिया से बिल्कुल विपरीत है।

यह समझने में मदद कर सकते हैं:

public class Customer { 
    // This field doesn't exist in the database 
    // It is simulated with a SQL query 
    // "OO speak": Customer owns the orders 
    private List<Order> orders; 
} 

public class Order { 
    // This field actually exists in the DB 
    // In a purely OO model, we could omit it 
    // "DB speak": Order contains a foreign key to customer 
    private Customer customer; 
} 

उलटा पक्ष ग्राहक इस मामले में, OO वस्तु के "मालिक" है। ऑर्डर को स्टोर करने के लिए ग्राहक में तालिका में कोई कॉलम नहीं है, इसलिए आपको यह बताना होगा कि ऑर्डर टेबल में यह डेटा कैसे सहेज सकता है (जो mappedBy के माध्यम से होता है)।

+33

बस स्पष्ट करने के लिए: कई तरफ मालिक है; एक तरफ उलटा है। आपके पास कोई विकल्प नहीं है (व्यावहारिक रूप से बोल रहा है)। – John

+0

स्पष्टीकरण हारून के लिए धन्यवाद। क्या कोई आरडीबीएमएस/एसक्यूएल पुस्तक उपलब्ध है जो समान शब्दावली (यानी उलटा/मालिक) का उपयोग करती है जहां मुझे इस विषय के बारे में अधिक जानकारी मिल सकती है? मेरे लिए अजीब बात यह भी थी कि जेपीए स्पेक में अंतर्निहित साधनों और किस तरह के मालिकों का विस्तृत परिभाषा नहीं था। यह सिर्फ इंगित किया गया था कि मैप किए गए गुण को विपरीत दिशा में होना चाहिए। – Behrang

+9

नहीं, हाइबरनेट ने इसका आविष्कार किया। मुझे यह पसंद नहीं है क्योंकि यह ओओ मॉडल के कार्यान्वयन का हिस्सा उजागर करता है। मैं "एक्सटीवाई" के बजाय एक '@ माता-पिता' या '@ चाइल्ड' एनोटेशन पसंद करूंगा, यह बताएगा कि कनेक्शन * का मतलब है * (यह कैसे * लागू किया गया है * के बजाय) –

33

डेटाबेस में विदेशी कुंजी के साथ तालिका वाली इकाई स्वामित्व वाली इकाई है और दूसरी तालिका, जिस पर इंगित किया जा रहा है, उलटा इकाई है।

+25

भी आसान: मालिक एफके कॉलम – jacktrades

+2

के साथ तालिका सरल और अच्छी व्याख्या है। किसी भी पक्ष मालिक बनाया जा सकता है। यदि हम ग्राहक क्षेत्र पर ऑर्डर.जावा में मैपडबी का उपयोग करते हैं <ग्राहक.जावा से मैप्डबी निकालें> तो एक नई तालिका ऑर्डर_Customer जैसी कुछ बनाई जाएगी जिसमें 2 कॉलम होंगे। ORDER_ID और CUSTOMER_ID। – HakunaMatata

37

अविश्वसनीय रूप से, 3 वर्षों में किसी ने आपके रिश्ते को मानचित्र बनाने के दोनों तरीकों के उदाहरणों के साथ आपके उत्कृष्ट प्रश्न का उत्तर नहीं दिया है।

जैसा कि अन्य लोगों द्वारा उल्लिखित है, "मालिक" पक्ष में डेटाबेस में सूचक (विदेशी कुंजी) शामिल है। आप किसी भी पक्ष को मालिक के रूप में नामित कर सकते हैं, हालांकि, यदि आप मालिक के रूप में एक पक्ष को नामित करते हैं, तो संबंध बिडरेक्शनल नहीं होगा (व्यस्त उर्फ ​​"कई" पक्ष को इसके "मालिक" का कोई ज्ञान नहीं होगा)। यह कैप्सूलीकरण/ढीला संयोजन के लिए वांछनीय हो सकता है:

// "One" Customer owns the associated orders by storing them in a customer_orders join table 
public class Customer { 
    @OneToMany(cascade = CascadeType.ALL) 
    private List<Order> orders; 
} 

// if the Customer owns the orders using the customer_orders table, 
// Order has no knowledge of its Customer 
public class Order { 
    // @ManyToOne annotation has no "mappedBy" attribute to link bidirectionally 
} 

केवल द्विदिश मानचित्रण समाधान "कई" पक्ष "एक" करने के लिए अपने सूचक ही है करने के लिए है, और @OneToMany "mappedBy" विशेषता का उपयोग करें। "मैप्डबी" विशेषता के बिना हाइबरनेट एक डबल मैपिंग की अपेक्षा करेगा (डेटाबेस में कॉलम और जॉइन टेबल दोनों शामिल होंगे, जो अनावश्यक (आमतौर पर अवांछित) है।

// "One" Customer as the inverse side of the relationship 
public class Customer { 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "customer") 
    private List<Order> orders; 
} 

// "many" orders each own their pointer to a Customer 
public class Order { 
    @ManyToOne 
    private Customer customer; 
} 
+1

आपके यूनिडायरेक्शनल उदाहरण में, जेपीए एक अतिरिक्त ग्राहक_ऑर्डर तालिका मौजूद होने की अपेक्षा करता है। जेपीए 2 के साथ आप ऑर्डर टेबल में डेटाबेस विदेशी कुंजी कॉलम को इंगित करने के लिए ग्राहक के ऑर्डर फ़ील्ड पर @ जोइन कॉलम एनोटेशन (जिसे मैं अक्सर उपयोग करना प्रतीत होता हूं) का उपयोग कर सकता हूं। इस तरह आपके पास जावा में एक यूनिडायरेक्शनल रिलेशनशिप है जबकि ऑर्डर टेबल में अभी भी एक विदेशी कुंजी कॉलम है। तो ऑब्जेक्ट वर्ल्ड में, ऑर्डर डेटाबेस के दौरान ग्राहक के बारे में नहीं जानता है, ग्राहक को ऑर्डर के बारे में पता नहीं है। –

+1

उबर-पूर्ण होने के लिए, आप बिडरेक्शनल केस दिखा सकते हैं जहां ग्राहक रिश्ते का स्वामित्व वाला पक्ष है। – HDave

3

दो इकाई वर्गों के लिए ग्राहक और आदेश, हाइबरनेट दो टेबल बनाएगा।

संभावित मामले:

  1. mappedBy Customer.java और Order.java कक्षा में नहीं किया जाता है को तात्कालिक>

    एक नया टेबल बनाया जाएगा ग्राहक पक्ष में [नाम = CUSTOMER_ORDER] जो होगा CUSTOMER_ID और ORDER_ID का मैपिंग रखें। ये ग्राहक और ऑर्डर टेबल्स की प्राथमिक कुंजी हैं। ऑर्डर पक्ष पर संबंधित ग्राहक_आईडी रिकॉर्ड मैपिंग को सहेजने के लिए एक अतिरिक्त कॉलम आवश्यक है।

  2. मैप्ड का उपयोग ग्राहक.जावा में किया जाता है [जैसा कि समस्या विवरण में दिया गया है] अब अतिरिक्त तालिका [CUSTOMER_ORDER] नहीं बनाई गई है। केवल आदेश तालिका में एक स्तंभ

  3. mappedby Order.java में प्रयोग किया जाता है अब अतिरिक्त तालिका हाइबरनेट द्वारा बनाया जाएगा। [नाम = CUSTOMER_ORDER] आदेश तालिका मानचित्रण के लिए अतिरिक्त स्तंभ [CUSTOMER_ID] नहीं होगा।

किसी भी पक्ष को रिश्ते के मालिक बनाया जा सकता है। लेकिन xxxToOne पक्ष चुनने के लिए यह बेहतर है।

कोडिंग प्रभाव -> केवल इकाई के पक्ष का स्वामित्व संबंध स्थिति बदल सकता है। नीचे उदाहरण में BoyFriend क्लास रिश्ते का मालिक है। भले ही गर्लफ्रेंड टूटना चाहती है, वह नहीं कर सकती।

import javax.persistence.*; 
import java.util.ArrayList; 
import java.util.List; 

@Entity 
@Table(name = "BoyFriend21") 
public class BoyFriend21 { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Boy_ID") 
    @SequenceGenerator(name = "Boy_ID", sequenceName = "Boy_ID_SEQUENCER", initialValue = 10,allocationSize = 1) 
    private Integer id; 

    @Column(name = "BOY_NAME") 
    private String name; 

    @OneToOne(cascade = { CascadeType.ALL }) 
    private GirlFriend21 girlFriend; 

    public BoyFriend21(String name) { 
     this.name = name; 
    } 

    public BoyFriend21() { 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public BoyFriend21(String name, GirlFriend21 girlFriend) { 
     this.name = name; 
     this.girlFriend = girlFriend; 
    } 

    public GirlFriend21 getGirlFriend() { 
     return girlFriend; 
    } 

    public void setGirlFriend(GirlFriend21 girlFriend) { 
     this.girlFriend = girlFriend; 
    } 
} 

import org.hibernate.annotations.*; 
import javax.persistence.*; 
import javax.persistence.CascadeType; 
import javax.persistence.Entity; 
import javax.persistence.Table; 
import java.util.ArrayList; 
import java.util.List; 

@Entity 
@Table(name = "GirlFriend21") 
public class GirlFriend21 { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Girl_ID") 
    @SequenceGenerator(name = "Girl_ID", sequenceName = "Girl_ID_SEQUENCER", initialValue = 10,allocationSize = 1) 
    private Integer id; 

    @Column(name = "GIRL_NAME") 
    private String name; 

    @OneToOne(cascade = {CascadeType.ALL},mappedBy = "girlFriend") 
    private BoyFriend21 boyFriends = new BoyFriend21(); 

    public GirlFriend21() { 
    } 

    public GirlFriend21(String name) { 
     this.name = name; 
    } 


    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public GirlFriend21(String name, BoyFriend21 boyFriends) { 
     this.name = name; 
     this.boyFriends = boyFriends; 
    } 

    public BoyFriend21 getBoyFriends() { 
     return boyFriends; 
    } 

    public void setBoyFriends(BoyFriend21 boyFriends) { 
     this.boyFriends = boyFriends; 
    } 
} 


import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.cfg.Configuration; 
import java.util.Arrays; 

public class Main578_DS { 

    public static void main(String[] args) { 
     final Configuration configuration = new Configuration(); 
     try { 
      configuration.configure("hibernate.cfg.xml"); 
     } catch (HibernateException e) { 
      throw new RuntimeException(e); 
     } 
     final SessionFactory sessionFactory = configuration.buildSessionFactory(); 
     final Session session = sessionFactory.openSession(); 
     session.beginTransaction(); 

     final BoyFriend21 clinton = new BoyFriend21("Bill Clinton"); 
     final GirlFriend21 monica = new GirlFriend21("monica lewinsky"); 

     clinton.setGirlFriend(monica); 
     session.save(clinton); 

     session.getTransaction().commit(); 
     session.close(); 
    } 
} 

import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.cfg.Configuration; 
import java.util.List; 

public class Main578_Modify { 

    public static void main(String[] args) { 
     final Configuration configuration = new Configuration(); 
     try { 
      configuration.configure("hibernate.cfg.xml"); 
     } catch (HibernateException e) { 
      throw new RuntimeException(e); 
     } 
     final SessionFactory sessionFactory = configuration.buildSessionFactory(); 
     final Session session1 = sessionFactory.openSession(); 
     session1.beginTransaction(); 

     GirlFriend21 monica = (GirlFriend21)session1.load(GirlFriend21.class,10); // Monica lewinsky record has id 10. 
     BoyFriend21 boyfriend = monica.getBoyFriends(); 
     System.out.println(boyfriend.getName()); // It will print Clinton Name 
     monica.setBoyFriends(null); // It will not impact relationship 

     session1.getTransaction().commit(); 
     session1.close(); 

     final Session session2 = sessionFactory.openSession(); 
     session2.beginTransaction(); 

     BoyFriend21 clinton = (BoyFriend21)session2.load(BoyFriend21.class,10); // Bill clinton record 

     GirlFriend21 girlfriend = clinton.getGirlFriend(); 
     System.out.println(girlfriend.getName()); // It will print Monica name. 
     //But if Clinton[Who owns the relationship as per "mappedby" rule can break this] 
     clinton.setGirlFriend(null); 
     // Now if Monica tries to check BoyFriend Details, she will find Clinton is no more her boyFriend 
     session2.getTransaction().commit(); 
     session2.close(); 

     final Session session3 = sessionFactory.openSession(); 
     session1.beginTransaction(); 

     monica = (GirlFriend21)session3.load(GirlFriend21.class,10); // Monica lewinsky record has id 10. 
     boyfriend = monica.getBoyFriends(); 

     System.out.println(boyfriend.getName()); // Does not print Clinton Name 

     session3.getTransaction().commit(); 
     session3.close(); 
    } 
} 
11

द्विदिश संबंधों के सरल नियम:

1. कई-से-एक द्विदिश रिश्ते, कई पक्ष हमेशा संबंधों के मालिक पक्ष है। उदाहरण: 1 कक्ष में कई व्यक्ति हैं (एक व्यक्ति केवल एक कमरा है) -> पक्ष का स्वामित्व व्यक्ति

2. एक-से-एक द्विपक्षीय संबंधों के लिए, स्वामित्व पक्ष उस पक्ष से मेल खाता है जिसमें संबंधित विदेशी कुंजी शामिल है।

3. कई से अधिक द्विपक्षीय संबंधों के लिए, दोनों तरफ स्वामित्व पक्ष हो सकता है।

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

+0

हमें मालिक और उलटा होने की आवश्यकता क्यों है? हमारे पास पहले से ही एक तरफ और कई तरफ की सार्थक अवधारणाएं हैं और इससे कोई फर्क नहीं पड़ता कि कई स्थितियों में मालिक कौन है। निर्णय के परिणाम क्या हैं? यह विश्वास करना मुश्किल है कि किसी डेटाबेस इंजीनियर के रूप में बाएं-दिमागी व्यक्ति को इन अनावश्यक अवधारणाओं को सिक्का देने का फैसला किया गया है। –

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