आप किस मामले में जेपीए @JoinTableएनोटेशन का उपयोग करते हैं?
आप किस मामले में जेपीए @JoinTableएनोटेशन का उपयोग करते हैं?
जवाबों:
EDIT 2017-04-29 : जैसा कि कुछ टिप्पणीकारों ने बताया है, JoinTableउदाहरण के लिए mappedByएनोटेशन विशेषता की आवश्यकता नहीं है । वास्तव में, हाइबरनेट के हाल के संस्करणों ने निम्नलिखित त्रुटि को प्रिंट करने से शुरू करने से इनकार कर दिया:
org.hibernate.AnnotationException:
Associations marked as mappedBy must not define database mappings
like @JoinTable or @JoinColumn
चलो बहाना करते हैं कि आपके पास नाम की एक इकाई है Projectऔर नाम की एक और इकाई है Taskऔर प्रत्येक परियोजना में कई कार्य हो सकते हैं।
आप डेटाबेस स्कीमा को दो तरीकों से इस परिदृश्य के लिए डिज़ाइन कर सकते हैं।
पहला समाधान नाम की एक तालिका बनाने के लिए है Projectऔर दूसरी तालिका नाम की है Taskऔर कार्य तालिका में एक विदेशी कुंजी कॉलम जोड़ें project_id:
Project Task
------- ----
id id
name name
project_id
इस तरह, कार्य तालिका में प्रत्येक पंक्ति के लिए परियोजना को निर्धारित करना संभव होगा। यदि आप अपनी इकाई कक्षाओं में इस दृष्टिकोण का उपयोग करते हैं, तो आपको ज्वाइन टेबल की आवश्यकता नहीं होगी:
@Entity
public class Project {
@OneToMany(mappedBy = "project")
private Collection<Task> tasks;
}
@Entity
public class Task {
@ManyToOne
private Project project;
}
अन्य समाधान तीसरी तालिका का उपयोग करना है, उदाहरण के लिए Project_Tasks, और उस तालिका में परियोजनाओं और कार्यों के बीच संबंधों को संग्रहीत करना है:
Project Task Project_Tasks
------- ---- -------------
id id project_id
name name task_id
Project_Tasksतालिका एक "में शामिल होने तालिका" कहा जाता है। जेपीए में इस दूसरे समाधान को लागू करने के लिए आपको @JoinTableएनोटेशन का उपयोग करने की आवश्यकता है । उदाहरण के लिए, एक-दिशात्मक एक से कई एसोसिएशन को लागू करने के लिए, हम अपनी संस्थाओं को इस तरह परिभाषित कर सकते हैं:
Project इकाई:
@Entity
public class Project {
@Id
@GeneratedValue
private Long pid;
private String name;
@JoinTable
@OneToMany
private List<Task> tasks;
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Task> getTasks() {
return tasks;
}
public void setTasks(List<Task> tasks) {
this.tasks = tasks;
}
}
Task इकाई:
@Entity
public class Task {
@Id
@GeneratedValue
private Long tid;
private String name;
public Long getTid() {
return tid;
}
public void setTid(Long tid) {
this.tid = tid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
यह निम्नलिखित डेटाबेस संरचना बनाएगा:
@JoinTableएनोटेशन भी आप तालिका में शामिल होने के विभिन्न पहलुओं को अनुकूलित करने देता। उदाहरण के लिए, क्या हमने tasksसंपत्ति को इस तरह से एनोटेट किया था :
@JoinTable(
name = "MY_JT",
joinColumns = @JoinColumn(
name = "PROJ_ID",
referencedColumnName = "PID"
),
inverseJoinColumns = @JoinColumn(
name = "TASK_ID",
referencedColumnName = "TID"
)
)
@OneToMany
private List<Task> tasks;
परिणामस्वरूप डेटाबेस बन जाएगा:
अंत में, यदि आप कई-से-कई एसोसिएशन के लिए एक स्कीमा बनाना चाहते हैं, तो ज्वाइन टेबल का उपयोग करना एकमात्र उपलब्ध समाधान है।
@JoinTable/@JoinColumnउसी क्षेत्र के साथ एनोटेट किया जा सकता है mappedBy। तो सही उदाहरण रखते हुए किया जाना चाहिए mappedByमें Project, और ले जाने के @JoinColumnलिए Task.project (या इसके विपरीत)
Project_Tasksकी जरूरत है nameकी Taskजो तीन कॉलम हो जाता है और साथ ही,: project_id, task_id, task_name, कैसे इस लक्ष्य को हासिल करने के लिए?
Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn:
यह भी उपयोग करने के लिए क्लीनर है @JoinTableजब कई माता-पिता / विभिन्न प्रकार के माता-पिता के साथ बच्चे के संबंधों में एक इकाई बच्चा हो सकता है। Behrang के उदाहरण के साथ पालन करने के लिए, एक कार्य की कल्पना करें परियोजना, व्यक्ति, विभाग, अध्ययन और प्रक्रिया का बच्चा हो सकता है।
क्या taskतालिका में 5 nullableविदेशी कुंजी फ़ील्ड होनी चाहिए ? मुझे नहीं लगता...
यह एक ManyToMany एसोसिएशन को मैप करने का एकमात्र समाधान है: आपको एसोसिएशन मैप करने के लिए दो एंटिटी टेबल के बीच एक ज्वाइन टेबल चाहिए।
यह OneToMany (आमतौर पर यूनिडायरेक्शनल) संघों के लिए भी उपयोग किया जाता है जब आप कई पक्ष की तालिका में एक विदेशी कुंजी नहीं जोड़ना चाहते हैं और इस तरह इसे एक तरफ से स्वतंत्र रखते हैं।
स्पष्टीकरण और उदाहरण के लिए हाइबरनेट प्रलेखन में @JoinTable के लिए खोजें ।
यह आपको कई से कई संबंधों को संभालने देता है। उदाहरण:
Table 1: post
post has following columns
____________________
| ID | DATE |
|_________|_________|
| | |
|_________|_________|
Table 2: user
user has the following columns:
____________________
| ID |NAME |
|_________|_________|
| | |
|_________|_________|
तालिका में शामिल होने से आप मानचित्रण का उपयोग कर सकते हैं:
@JoinTable(
name="USER_POST",
joinColumns=@JoinColumn(name="USER_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="POST_ID", referencedColumnName="ID"))
एक तालिका बनाएंगे:
____________________
| USER_ID| POST_ID |
|_________|_________|
| | |
|_________|_________|
@ManyToMany संघोंसबसे अधिक बार, आपको @JoinTableकई-कई तालिका संबंधों की मैपिंग को निर्दिष्ट करने के लिए एनोटेशन का उपयोग करने की आवश्यकता होगी :
तो, मान लें कि आपके पास निम्नलिखित डेटाबेस टेबल हैं:
में Postइकाई, तो आप इस संबंध है, इस तरह के नक्शे होगा:
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private List<Tag> tags = new ArrayList<>();
@JoinTableटिप्पणी द्वारा तालिका नाम निर्दिष्ट करने के लिए प्रयोग किया जाता है nameविशेषता है, साथ ही विदेशी कुंजी स्तंभ संदर्भ postतालिका (जैसे, joinColumns) और में विदेशी कुंजी स्तंभ post_tagलिंक तालिका संदर्भ Tagके माध्यम से इकाई inverseJoinColumnsविशेषता।
ध्यान दें कि
@ManyToManyएनोटेशन की कैस्केड विशेषता केवलPERSISTऔरMERGEकेवल इसलिए सेट की जाती है क्योंकि कैस्केडिंगREMOVEएक बुरा विचार है क्योंकि हम DELETE स्टेटमेंट को अन्य पैरेंट रिकॉर्ड के लिए जारी किया जाएगा,tagहमारे मामले में रिकॉर्ड में नहींpost_tag। इस विषय के बारे में अधिक जानकारी के लिए, इस लेख को देखें ।
@OneToManyसंघयूनिडायरेक्शनल @OneToManyएसोसिएशन, जिसमें एक @JoinColumnमैपिंग की कमी है , एक -से-कई के बजाय कई-टू-टेबल संबंधों की तरह व्यवहार करते हैं।
तो, मान लें कि आपके पास निम्नलिखित इकाई मैपिंग हैं:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
}
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
//Constructors, getters and setters removed for brevity
}
हाइबरनेट उपरोक्त निकाय मानचित्रण के लिए निम्नलिखित डेटाबेस स्कीमा ग्रहण करेगा:
जैसा कि पहले ही समझाया गया है, यूनिडायरेक्शनल @OneToManyजेपीए मैपिंग कई-से-कई एसोसिएशन की तरह व्यवहार करता है।
लिंक तालिका को अनुकूलित करने के लिए, आप @JoinTableएनोटेशन का भी उपयोग कर सकते हैं :
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
@JoinTable(
name = "post_comment_ref",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "post_comment_id")
)
private List<PostComment> comments = new ArrayList<>();
और अब, लिंक तालिका के नाम से जाना जा रहा है post_comment_refऔर विदेशी कुंजी स्तंभ हो जाएगा post_idके लिए, postमेज, और post_comment_idके लिए, post_commentतालिका।
यूनिडायरेक्शनल
@OneToManyएसोसिएशन कुशल नहीं हैं, इसलिए आप द्विदिश@OneToManyसंघों या सिर्फ@ManyToOneपक्ष का उपयोग कर बेहतर हैं । की जाँच करें इस लेख में इस विषय के बारे में अधिक जानकारी के लिए।