क्या कोई जेपीए और हाइबरनेट में मैप्डबी की व्याख्या कर सकता है?


175

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

  • इसका उपयोग करने के लिए अनुशंसित तरीका क्या है?
  • इसका क्या उद्देश्य है?

मेरे उदाहरण के लिए, यहां एनोटेशन के साथ मेरी कक्षाएं हैं:

  • Airline OWNS कई AirlineFlights
  • कई AirlineFlights से संबंधित एक Airline

एयरलाइन :

@Entity 
@Table(name="Airline")
public class Airline {
    private Integer idAirline;
    private String name;

    private String code;

    private String aliasName;
    private Set<AirlineFlight> airlineFlights = new HashSet<AirlineFlight>(0);

    public Airline(){}

    public Airline(String name, String code, String aliasName, Set<AirlineFlight> flights) {
        setName(name);
        setCode(code);
        setAliasName(aliasName);
        setAirlineFlights(flights);
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="IDAIRLINE", nullable=false)
    public Integer getIdAirline() {
        return idAirline;
    }

    private void setIdAirline(Integer idAirline) {
        this.idAirline = idAirline;
    }

    @Column(name="NAME", nullable=false)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = DAOUtil.convertToDBString(name);
    }

    @Column(name="CODE", nullable=false, length=3)
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = DAOUtil.convertToDBString(code);
    }

    @Column(name="ALIAS", nullable=true)
    public String getAliasName() {
        return aliasName;
    }
    public void setAliasName(String aliasName) {
        if(aliasName != null)
            this.aliasName = DAOUtil.convertToDBString(aliasName);
    }

    @OneToMany(fetch=FetchType.LAZY, cascade = {CascadeType.ALL})
    @JoinColumn(name="IDAIRLINE")
    public Set<AirlineFlight> getAirlineFlights() {
        return airlineFlights;
    }

    public void setAirlineFlights(Set<AirlineFlight> flights) {
        this.airlineFlights = flights;
    }
}

AirlineFlights:

@Entity
@Table(name="AirlineFlight")
public class AirlineFlight {
    private Integer idAirlineFlight;
    private Airline airline;
    private String flightNumber;

    public AirlineFlight(){}

    public AirlineFlight(Airline airline, String flightNumber) {
        setAirline(airline);
        setFlightNumber(flightNumber);
    }

    @Id
    @GeneratedValue(generator="identity")
    @GenericGenerator(name="identity", strategy="identity")
    @Column(name="IDAIRLINEFLIGHT", nullable=false)
    public Integer getIdAirlineFlight() {
        return idAirlineFlight;
    }
    private void setIdAirlineFlight(Integer idAirlineFlight) {
        this.idAirlineFlight = idAirlineFlight;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="IDAIRLINE", nullable=false)
    public Airline getAirline() {
        return airline;
    }
    public void setAirline(Airline airline) {
        this.airline = airline;
    }

    @Column(name="FLIGHTNUMBER", nullable=false)
    public String getFlightNumber() {
        return flightNumber;
    }
    public void setFlightNumber(String flightNumber) {
        this.flightNumber = DAOUtil.convertToDBString(flightNumber);
    }
}

संपादित करें:

डेटाबेस स्कीमा:

AirlineFlights के पास IdAirline है जैसा कि विदेश में है और Airline के पास कोई IdAirlineFlights नहीं है। यह मालिक / पहचान इकाई के रूप में AirlineFlights बनाता है?

सैद्धांतिक रूप से, मैं चाहूंगा कि एयरलाइन एयरलाइन एयरलाइंस का मालिक हो।

यहां छवि विवरण दर्ज करें

जवाबों:


151

@JoinColumnदोनों मॉडलों पर निर्दिष्ट करके आप एक दो तरह से संबंध नहीं है। आपके पास दो तरह के रिश्ते हैं, और उस पर बहुत भ्रमित करने वाली मैपिंग है। आप दोनों मॉडलों को बता रहे हैं कि वे IDAIRLINE कॉलम "स्वयं" करते हैं। वास्तव में उनमें से केवल एक ही वास्तव में होना चाहिए! 'सामान्य' बात यह है @JoinColumnकि @OneToManyपक्ष को पूरी तरह से बंद कर दिया जाए , और इसके बजाय मैप किए जाएं @OneToMany

@OneToMany(cascade = CascadeType.ALL, mappedBy="airline")
public Set<AirlineFlight> getAirlineFlights() {
    return airlineFlights;
}

यह हाइबरनेट को बताता है कि "इस बात पर 'एयरलाइन' नाम की सेम की संपत्ति पर जाएं, मेरे पास कॉन्फ़िगरेशन खोजने के लिए एक संग्रह है।"


2
मैं mappedBy के बारे में अंत में आपके विवरण से थोड़ा भ्रमित हूं। क्या इससे कोई फर्क नहीं पड़ता कि कैसे चीजें डीबी में व्यवस्थित होती हैं? @DB: एयरलाइनलाइन पर विदेशी कुंजी के रूप में आईडीलाइन है। एयरलाइन में केवल प्राथमिक कुंजी के रूप में idAirline है और AirlineFlights @ DB के बारे में जानकारी नहीं देता है।
brainydexter

10
हां, इससे फर्क पड़ता है। मैप्डबाय में नाम हाइबरनेट को बता रहा है कि JoinColumn के लिए कॉन्फ़िगरेशन कहां खोजना है। (AirlineFlight की विधि getAirline () पर।) जिस तरह से आप एयरलाइन पर JoinColumn डाल, तो आप एयरलाइन है कि यह कह रहे हैं यह मैप किया गया है अन्य तालिका में अधिक मूल्यों को बनाए रखने के लिए जिम्मेदार है। एक इकाई को एक अलग तालिका में "स्वामी" "स्तंभ" बताना संभव है और इसे अद्यतन करने के लिए जिम्मेदार है। यह ऐसा कुछ नहीं है जिसे आप आमतौर पर करना चाहते हैं और SQL कथन निष्पादित किए जाने वाले आदेश के साथ समस्याएं पैदा कर सकते हैं।
Aff

कृपया संपादन देखें। DB स्तर पर, एयरलाइनफ़्लाइट टेबल एक विदेशी कुंजी कॉलम के रूप में idAirline का मालिक है। इसलिए, JoinColumn को संबंधित ManytoOne में एयरलाइनफ़्लाइट क्लास / टेबल पर रखा जाना चाहिए, क्योंकि यह उस कॉलम का मालिक है?
ब्रेनडेक्सटर

हां, मैं इसे इस तरह से करने की सलाह दूंगा। यह कम से कम जटिल विकल्प है और आपको किसी और चीज की आवश्यकता नहीं है।
Affe

"@OoinTolumn को @OneToMany साइड से पूरी तरह से बंद कर दें" का मतलब है कि आप @ManyToOneसही पक्ष के हैं?
नभ

284

मैप्डबी सिग्नल को संकेत देता है कि रिश्ते की कुंजी दूसरी तरफ है।

इसका मतलब यह है कि यद्यपि आप 2 तालिकाओं को एक साथ जोड़ते हैं, उनमें से केवल 1 तालिका में अन्य के लिए एक विदेशी कुंजी बाधा है। मैप्डबी आपको अभी भी तालिका से लिंक करने की अनुमति देता है जिसमें बाधा नहीं है अन्य तालिका से।


3
क्या आप कृपया कुछ और स्पष्ट कर सकते हैं?
अलेक्जेंडर सुरफेल

1
@ कर्ट डू बोइस, आप mappedByएक द्वि-दिशात्मक (प्रत्येक तरफ विदेशी_की बाधाओं के साथ) को परिभाषित करने के बजाय क्यों इस्तेमाल करेंगे ?
केविन मेरेडिथ

6
क्योंकि कभी-कभी दोनों तरफ से चाबी लगाने का कोई मतलब नहीं होता है। उदाहरण के लिए कहें कि आपके पास एक कंपनी और एक पोर्टेबल है। एक पोर्टेबल केवल एक कंपनी का होगा, लेकिन एक कंपनी के कई पोर्टेबल्स होंगे।
कर्ट डू बोइस

मेरे उत्तर को वापस लाने के लिए संपादन करने वाले को क्षमा करें, लेकिन आपके संपादन में वास्तव में कोई अतिरिक्त मूल्य नहीं था। आखिरी वाक्य भी समझ में नहीं आया।
कर्ट डू बोइस

@ कुर्टडूइस तो केवल तस्वीर में आकर मैप किया जाता है कि कैसे अपने डेटाबेस का निर्माण कर रहे हैं, यानी या तो मैप का उपयोग करके या जावा साइड में हाइबरनेट का उपयोग नहीं करना चाहिए। यह समान है।

22

mappedbyखुद के लिए बोलता है, यह हाइबरनेट बताता है कि इस क्षेत्र को मैप न करें। यह पहले से ही इस क्षेत्र [नाम = "फ़ील्ड"] द्वारा मैप किया गया है।
फ़ील्ड दूसरी इकाई में है (name of the variable in the class not the table in the database)..

यदि आप ऐसा नहीं करते हैं, तो हाइबरनेट इस दो संबंध को मैप करेगा क्योंकि यह समान संबंध नहीं है

इसलिए हमें हाइबरनेट को केवल एक पक्ष में मैपिंग करने और उनके बीच समन्वय बनाने की आवश्यकता है।


क्या मैप किया गया है वैकल्पिक? क्योंकि बिना मैप का उपयोग किए मुझे एक ही परिणाम मिल रहा है अर्थात द्विदिश वस्तु मैपिंग
फ्रीलांसर

आप on2many और many2one का उपयोग नहीं कर सकते बिना मैप किए हुए किसी एक पक्ष में एक ही चीज़ का उपयोग कर सकते हैं कई2many के लिए आपको एक पक्ष में मैप्डबी का उपयोग करना होगा
Charif DZ

यह इंगित करने के लिए धन्यवाद कि विशेषता मान का अर्थ क्या है जो अन्य तालिका में फ़ील्ड का नाम है।
गब 是

2
शायद हाइबरनेट हमेशा खुद के लिए नहीं बोलता, लेकिन जब यह करता है, तो कम से कम विराम चिह्न का उपयोग करता है
Amalgovinus

1
मेरे लिए, यह खुद के लिए नहीं बोलता है; इसके विपरीत, यह बहुत भ्रामक है। वास्तव में क्या है mappedByऔर इसके बारे में प्रश्नों की मात्रा को देखें inversedBy। अन्य ORM अधिक बुद्धिमान belongsToMany, hasManyविशेषताओं का उपयोग करते हैं ।
जन बोधनार

12

मैप्डबी = "दूसरी कक्षा में बनाई गई उसी वर्ग की इकाई की वस्तु"

नोट: -Mapped द्वारा केवल एक वर्ग में उपयोग किया जा सकता है क्योंकि एक टेबल में विदेशी कुंजी बाधा होनी चाहिए। यदि दोनों तरफ से मैप किया जा सकता है तो यह दोनों टेबल से विदेशी कुंजी को हटा देता है और विदेशी कुंजी के बिना कोई संबंध नहीं है b / w दो टेबल।

नोट: - इसका उपयोग एनोटेशन के लिए किया जा सकता है: - 1. @ OneTone 2. @ OneToMany 3. @ ManyToMany

नोट --- इसका उपयोग एनोटेशन के लिए नहीं किया जा सकता है: - 1. @ ManyToOne

एक से एक में: - मैपिंग के किसी भी पक्ष पर प्रदर्शन करें, लेकिन केवल एक तरफ ही करें। यह उस मेज पर विदेशी कुंजी बाधा के अतिरिक्त कॉलम को हटा देगा जिस पर इसे लागू किया गया है।

उदाहरण के लिए। यदि हम कर्मचारी वस्तु पर कर्मचारी वर्ग द्वारा मैप किया गया है तो कर्मचारी तालिका से विदेशी कुंजी हटा दी जाएगी।


12

तालिका संबंध बनाम इकाई संबंध

एक संबंधपरक डेटाबेस प्रणाली में, एक one-to-manyतालिका संबंध निम्नानुसार दिखता है:

<code> एक-से-कई </ code> तालिका संबंध

ध्यान दें कि संबंध post_idचाइल्ड टेबल में फॉरेन की कॉलम (जैसे ) पर आधारित है ।

इसलिए, जब one-to-manyतालिका संबंध का प्रबंधन करने की बात आती है, तो सच्चाई का एक ही स्रोत होता है ।

अब, यदि आप एक द्विदिश इकाई संबंध लेते हैं जो one-to-manyपहले देखे गए तालिका संबंध पर मैप करता है :

द्विदिश <कोड> एक-से-कई </ कोड> इकाई संघ

यदि आप ऊपर दिए गए आरेख पर एक नज़र डालते हैं, तो आप देख सकते हैं कि इस संबंध को प्रबंधित करने के दो तरीके हैं।

में Postइकाई, आपके पास commentsसंग्रह:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

और, में PostComment, postएसोसिएशन निम्नानुसार मैप किया गया है:

@ManyToOne(
    fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;

क्योंकि फॉरेन की कॉलम को दर्शाने के दो तरीके हैं, इसलिए आपको यह परिभाषित करना चाहिए कि जब एसोसिएशन राज्य परिवर्तन को अपने समकक्ष फॉरेन के कॉलम वैल्यू मॉडिफिकेशन में बदलने की बात करता है, तो सच्चाई का स्रोत है।

MappedBy

mappedByविशेषता बताता है कि @ManyToOneपक्ष विदेशी कुंजी स्तंभ के प्रबंधन का कार्यभार में है, और संग्रह इकलौती संतान संस्थाओं को लाने के लिए प्रयोग किया जाता है बच्चों के लिए झरना मूल इकाई राज्य परिवर्तन करने के लिए (जैसे, माता पिता को दूर भी बच्चे संस्थाओं को दूर करना चाहिए)।

एक द्विदिश संघ के दोनों पक्षों को सिंक्रनाइज़ करें

अब, भले ही आपने mappedByविशेषता को परिभाषित किया हो और चाइल्ड-साइड @ManyToOneएसोसिएशन विदेशी कुंजी कॉलम का प्रबंधन करता है, फिर भी आपको द्विदिश संघ के दोनों पक्षों को सिंक्रनाइज़ करने की आवश्यकता है।

इन दो उपयोगिता विधियों को जोड़ने का सबसे अच्छा तरीका है:

public void addComment(PostComment comment) {
    comments.add(comment);
    comment.setPost(this);
}

public void removeComment(PostComment comment) {
    comments.remove(comment);
    comment.setPost(null);
}

addCommentऔर removeCommentतरीकों सुनिश्चित करना है कि दोनों पक्षों सिंक्रनाइज़ किए जाते हैं। इसलिए, यदि हम एक बाल इकाई को जोड़ते हैं, तो बाल इकाई को माता-पिता को इंगित करने की आवश्यकता होती है और माता-पिता इकाई को बच्चे को बाल संग्रह में समाहित करना चाहिए।

सभी द्विदिश इकाई संघ प्रकारों को सिंक्रनाइज़ करने के सर्वोत्तम तरीके के बारे में अधिक विवरण के लिए, इस लेख को देखें


0

आपने ManyToOne मैपिंग के साथ शुरुआत की, फिर आपने OneToMany मैपिंग के साथ-साथ BiDirectional तरीके से भी काम किया। फिर OneToMany साइड (आमतौर पर आपकी पैरेंट टेबल / क्लास) में, आपको "मैप्डबी" (मैपिंग द्वारा और चाइल्ड टेबल / क्लास में किया जाता है) का उल्लेख करना होता है, इसलिए हाइबरनेट डीबी (जैसे टेबलनेम = पैरेंट_चाइल्ड) में एक्स्ट्रा मैपिंग टेबल नहीं बनाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.