ความแตกต่างระหว่างหนึ่งต่อหลายหลายต่อหนึ่งและหลายต่อหลายคน?


144

ตกลงดังนั้นนี่อาจเป็นคำถามเล็กน้อย แต่ฉันมีปัญหาในการมองเห็นและเข้าใจความแตกต่างและเวลาที่จะใช้แต่ละครั้ง ฉันยังไม่ชัดเจนว่าแนวคิดเช่นการแมปแบบทิศทางเดียวและแบบสองทิศทางมีผลต่อความสัมพันธ์แบบหนึ่งต่อหลาย / หลายต่อหลายครั้งอย่างไร ฉันกำลังใช้ Hibernate อยู่ตอนนี้ดังนั้นคำอธิบายใด ๆ ที่เกี่ยวข้องกับ ORM จะเป็นประโยชน์

ตัวอย่างเช่นสมมติว่าฉันมีการตั้งค่าต่อไปนี้:

public class Person{
    private Long personId;
    private Set<Skill> skills;
    //Getters and setters
}

public class Skill{
    private Long skillId;
    private String skillName;
    //Getters and setters
}

ดังนั้นในกรณีนี้ฉันจะมีการทำแผนที่แบบไหน? คำตอบสำหรับตัวอย่างเฉพาะนี้ได้รับการชื่นชมอย่างแน่นอน แต่ฉันก็อยากจะเห็นภาพรวมของเวลาที่จะใช้แบบตัวต่อตัวและแบบตัวต่อตัวและเมื่อใดที่จะใช้ตารางการเข้าร่วมกับคอลัมน์การเข้าร่วมและทิศทางเดียวกับแบบสองทิศทาง


11
ดูเหมือนว่าทุกคนจะตอบกลับแบบหนึ่งต่อหลายคนและหลายต่อหลายคนเท่านั้น ดูคำตอบของฉันสำหรับหนึ่งต่อหลายเทียบกับหลายต่อหนึ่ง
Alexander Suraphel

คำตอบ:


165

หนึ่งต่อหลาย : หนึ่งคนมีทักษะมากมายทักษะไม่ได้ถูกนำมาใช้ซ้ำระหว่างบุคคล

  • ทิศทางเดียว : บุคคลสามารถอ้างอิงทักษะโดยตรงผ่านชุดของมัน
  • แบบสองทิศทาง : ทักษะ "เด็ก" แต่ละคนมีตัวชี้เดียวกลับไปยังบุคคล (ซึ่งไม่ได้แสดงในรหัสของคุณ)

หลายต่อหลายคน : หนึ่งคนมีทักษะมากมายทักษะจะถูกนำมาใช้ใหม่ระหว่างบุคคล

  • ทิศทางเดียว : บุคคลสามารถอ้างอิงทักษะโดยตรงผ่านชุดของมัน
  • แบบสองทิศทาง : ทักษะมีชุดของบุคคลที่เกี่ยวข้องกับมัน

ในความสัมพันธ์แบบตัวต่อตัววัตถุหนึ่งคือ "พาเรนต์" และอีกอันคือ "ลูก" ผู้ปกครองควบคุมการดำรงอยู่ของเด็ก ในหลายต่อหลายคนการมีอยู่ของทั้งสองประเภทจะขึ้นอยู่กับบางสิ่งที่อยู่นอกทั้งคู่ (ในบริบทของแอปพลิเคชันที่ใหญ่กว่า)

หัวเรื่อง (โดเมน) ของคุณควรกำหนดว่าความสัมพันธ์นั้นเป็นแบบ One-To-Many หรือ Many-To-Many อย่างไรก็ตามฉันพบว่าการสร้างความสัมพันธ์แบบทิศทางเดียวหรือแบบสองทิศทางเป็นการตัดสินใจทางวิศวกรรมที่แลกเปลี่ยนความจำการประมวลผลประสิทธิภาพ ฯลฯ

สิ่งที่อาจทำให้สับสนคือความสัมพันธ์แบบสองทิศทางต่อหลายคนไม่จำเป็นต้องสมมาตร! นั่นคือคนจำนวนมากอาจชี้ไปที่ทักษะ แต่ทักษะนั้นไม่จำเป็นต้องเกี่ยวข้องกับคนเหล่านั้น โดยทั่วไปแล้วจะได้ แต่สมมาตรดังกล่าวไม่ได้เป็นข้อกำหนด ยกตัวอย่างเช่นรัก - มันเป็นแบบสองทิศทาง ("I-Love", "Loves-Me") แต่มักจะไม่สมมาตร ("ฉันรักเธอ แต่เธอไม่รักฉัน")!

ทั้งหมดนี้ได้รับการสนับสนุนอย่างดีจาก Hibernate และ JPA เพียงจำไว้ว่าไฮเบอร์เนตหรือ ORM อื่นใดจะไม่บีบแตรเกี่ยวกับการรักษาความสมมาตรเมื่อจัดการความสัมพันธ์แบบหลายต่อหลายทิศทาง ... นั่นขึ้นอยู่กับแอปพลิเคชัน


ในการชี้แจงความสัมพันธ์ใด ๆ อาจเป็นหนึ่งเดียวหรือสองทิศทางใน BL ของคุณหรือในการทำแผนที่ O / R ของคุณ (เป็นอิสระจากกันแม้แต่!)
jyoungdev

4
ตัวอย่าง "ความรัก" เพียงแค่ชี้แจง ManyToMany เป็นแผนที่ประเภทของฉัน
อับดุลลาห์ข่าน

1
ซูเปอร์ สิ่งนี้อธิบายได้ดีมาก (และในบริบทของตัวอย่างของ OP)
Anupam

1
ไม่ตอบคำถามอย่างถูกต้อง คุณคิดถึงหลายต่อส่วน แม้ว่าหนึ่งถึงมากและหลายต่อหลายเป็นเรื่องของการรับรู้คำตอบนี้ไม่ได้พูดถึงว่า
Manzur Alahi

249

ดูเหมือนว่าทุกคนกำลังตอบรับOne-to-manyกับMany-to-many:

ความแตกต่างระหว่าง One-to-many , Many-to-oneและMany-to-Manyเป็น:

One-to-manyเทียบMany-to-oneเป็นเรื่องของมุมมอง Unidirectionalvs Bidirectionalจะไม่ส่งผลกระทบต่อการทำแผนที่ แต่จะสร้างความแตกต่างในการเข้าถึงข้อมูลของคุณ

  • ในด้านจะทำให้การอ้างอิงของด้านข้าง ตัวอย่างที่ดีคือ "รัฐมีเมือง" ในกรณีนี้คือด้านหนึ่งและMany-to-onemanyoneStateCityเป็นหลายด้าน จะมีคอลัมน์ในตารางstate_idcities

ในทิศทางเดียว , Personชั้นจะมีList<Skill> skillsแต่ จะไม่ได้มีSkill Person personในแบบสองทิศทางคุณสมบัติทั้งสองจะถูกเพิ่มและช่วยให้คุณเข้าถึงPersonทักษะที่กำหนด (เช่นskill.person)

  • ในOne-to-Manyด้านหนึ่งจะเป็นจุดอ้างอิงของเรา ตัวอย่างเช่น "ผู้ใช้มีที่อยู่" ในกรณีนี้เราอาจจะมีคอลัมน์ที่สามaddress_1_id, address_2_idและaddress_3_idหรือมองขึ้นตารางที่มีข้อ จำกัด ที่ไม่ซ้ำกันuser_idaddress_idและ

ในทิศทางเดียวที่จะมีUser แบบสองทิศทาง จะมีเพิ่มเติมในชั้นเรียนAddress addressList<User> usersAddress

  • ในMany-to-Manyสมาชิกของแต่ละฝ่ายสามารถถือการอ้างอิงถึงจำนวนสมาชิกของอีกฝ่ายโดยพลการ เพื่อให้บรรลุนี้มีการใช้ตารางค้นหา ตัวอย่างนี้คือความสัมพันธ์ระหว่างแพทย์และผู้ป่วย แพทย์สามารถมีผู้ป่วยจำนวนมากและในทางกลับกัน

27
นี่ควรเป็นคำตอบที่ได้รับการยอมรับส่วนใหญ่คำตอบอื่น ๆ คิดถึงคำถาม
arg20

ตัวอย่างแรกไม่ถูกต้อง หากคุณมี A บุคคลและบุคคลที่มี @OneToMany พร้อมด้วยทักษะ preson_skills นั้นจะมีข้อ จำกัด ที่ไม่ซ้ำกันใน skill_id ดังนั้นทักษะหนึ่งจะถูกแมปกับบุคคลเดียวเท่านั้น และคุณไม่สามารถแยกได้s.personsเนื่องจากมีเพียงs.person
ИванНиколайчук

One-to-manyความสัมพันธ์จริงตามที่คุณอธิบายคือMany-to-manyความสัมพันธ์เพราะpersonมีการอ้างอิงถึงหลายคนskillsแต่skillไม่ได้อ้างอิงถึงบุคคลใดบุคคลหนึ่งและหลายคนpersonsสามารถมีการอ้างอิงเดียวกันskillได้ และMany-to-oneความสัมพันธ์ของคุณเป็นจริงOne-to-manyเพราะทักษะแต่ละอย่างมีการอ้างอิงถึงหนึ่งเดียวเท่านั้นpersonเพราะเด็กมีแม่เพียงคนเดียว
mixel

@mixel ความคิดเห็นของคุณท้ายทำให้ฉันเขียนคำตอบของฉันส่วนใหญ่ โปรดตรวจสอบอีกครั้ง! ขอบคุณ
Alexander Suraphel

คุณเห็นความแตกต่างระหว่างหนึ่งต่อหลายและหลายต่อหนึ่งโดยความสำคัญของด้าน "หนึ่ง" ในทั้งสองตัวอย่าง "ผู้ใช้" เป็นเอนทิตีที่สำคัญที่สุด ดังนั้นเมื่ออยู่ใน "One" (ผู้ใช้และทักษะskillsมีperson_id) คุณจะเรียกมันว่า One-to-Many แต่เมื่อเป็นด้านหนึ่ง "หลาย" (ผู้ใช้และที่อยู่usersมีaddress_id) คุณจะเรียกมันว่าหลายต่อหนึ่ง แต่โครงสร้างทั้งสองกรณีนั้นเหมือนกันและเรียกว่า One-to-many
mixel

38

1) แวดวงคือเอนทิตี / POJOs / ถั่ว

2) deg เป็นตัวย่อขององศาในกราฟ (จำนวนขอบ)

PK = คีย์หลัก, FK = foreign key

สังเกตความขัดแย้งระหว่างระดับและชื่อของด้านข้าง หลายคนสอดคล้องกับดีกรี = 1 ในขณะที่หนึ่งสอดคล้องกับดีกรี> 1

ภาพประกอบของแบบหนึ่งต่อหลายคน


1
ชอบที่จะผูกกราฟวัตถุกับตารางทั้งสองทิศทาง
Dmitry Minkovsky

3
nerds ดูนี้เป็นวิธีที่โปรแกรมเมอร์ เขียนด้วยลายมือลักษณะเหมือน: D
Mehraj มาลิก

ฉันเห็นสิ่งที่คุณทำที่นี่
Nick Gallimore

8

ลองดูที่บทความนี้: การทำแผนที่ความสัมพันธ์ของวัตถุ

มีความสัมพันธ์ของวัตถุสองประเภทที่คุณต้องคำนึงถึงเมื่อทำการแมป ประเภทแรกขึ้นอยู่กับหลายหลากและมีสามประเภท:

*One-to-one relationships.  This is a relationship where the maximums of each of its multiplicities is one, an example of which is holds relationship between Employee and Position in Figure 11.  An employee holds one and only one position and a position may be held by one employee (some positions go unfilled).
*One-to-many relationships. Also known as a many-to-one relationship, this occurs when the maximum of one multiplicity is one and the other is greater than one.  An example is the works in relationship between Employee and Division.  An employee works in one division and any given division has one or more employees working in it.
*Many-to-many relationships. This is a relationship where the maximum of both multiplicities is greater than one, an example of which is the assigned relationship between Employee and Task.  An employee is assigned one or more tasks and each task is assigned to zero or more employees. 

ประเภทที่สองขึ้นอยู่กับทิศทางและมีสองประเภทความสัมพันธ์แบบทิศทางเดียวและความสัมพันธ์แบบสองทิศทาง

*Uni-directional relationships.  A uni-directional relationship when an object knows about the object(s) it is related to but the other object(s) do not know of the original object.  An example of which is the holds relationship between Employee and Position in Figure 11, indicated by the line with an open arrowhead on it.  Employee objects know about the position that they hold, but Position objects do not know which employee holds it (there was no requirement to do so).  As you will soon see, uni-directional relationships are easier to implement than bi-directional relationships.
*Bi-directional relationships.  A bi-directional relationship exists when the objects on both end of the relationship know of each other, an example of which is the works in relationship between Employee and Division.  Employee objects know what division they work in and Division objects know what employees work in them. 

2
this occurs when the maximum of one multiplicity is one and the other is greater than onelolwut?
serg

3

นี่เป็นคำถามที่พบบ่อยมากดังนั้นคำตอบนี้เป็นไปตามบทความที่ฉันเขียนในบล็อกของฉัน

หนึ่งต่อหลายคน

ความสัมพันธ์ของตารางแบบหนึ่งต่อกลุ่มมีลักษณะดังนี้:

หนึ่งต่อหลายคน

ในระบบฐานข้อมูลเชิงสัมพันธ์ความสัมพันธ์แบบหนึ่งต่อหลายตารางจะเชื่อมโยงสองตารางตามForeign Keyคอลัมน์ในคอลัมน์ย่อยที่อ้างอิงถึงPrimary Keyแถวของตารางหลัก

ในแผนภาพตารางด้านบนpost_idคอลัมน์ในpost_commentตารางมีForeign Keyความสัมพันธ์กับคอลัมน์postรหัสตารางPrimary Key:

ALTER TABLE
    post_comment
ADD CONSTRAINT
    fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post

@ManyToOne คำอธิบายประกอบ

วิธีที่ดีที่สุดในการแมปความสัมพันธ์ของตารางหนึ่งต่อหลายคือการใช้ @ManyToOneคำอธิบายประกอบ

ในกรณีของเราเอนทิตีสำหรับเด็กPostCommentแม็พpost_idคอลัมน์ Foreign Key โดยใช้@ManyToOneหมายเหตุประกอบ:

@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {

    @Id
    @GeneratedValue
    private Long id;

    private String review;

    @ManyToOne(fetch = FetchType.LAZY)
    private Post post;

}

ใช้ JPA @OneToManyคำอธิบายประกอบ

เพียงเพราะคุณมีตัวเลือกในการใช้@OneToManyคำอธิบายประกอบมันไม่ได้หมายความว่านี่ควรเป็นตัวเลือกเริ่มต้นสำหรับทุกๆ คนความสัมพันธ์ฐานข้อมูลปัญหาเกี่ยวกับคอลเลกชันคือเราสามารถใช้งานได้ก็ต่อเมื่อจำนวนเรคคอร์ดย่อยมี จำกัด

วิธีที่ดีที่สุดในการแมปการ@OneToManyเชื่อมโยงคือการพึ่งพา@ManyToOneด้านข้างเพื่อเผยแพร่การเปลี่ยนแปลงสถานะของเอนทิตีทั้งหมด:

@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    @GeneratedValue
    private Long id;

    private String title;

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

    //Constructors, getters and setters removed for brevity

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

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

หน่วยงานหลักPost, มีคุณสมบัติสองวิธีการยูทิลิตี้ (เช่นaddCommentและremoveComment) ซึ่งจะใช้ในการประสานทั้งสองด้านของการเชื่อมโยงแบบสองทิศทาง คุณควรให้วิธีการเหล่านี้ทุกครั้งที่คุณทำงานกับสมาคมแบบสองทิศทางในทางอื่น ๆ มิฉะนั้นคุณก็เสี่ยงต่อการแพร่กระจายของปัญหาที่ละเอียดอ่อนมากประเด็นการขยายพันธุ์ของรัฐที่ลึกซึ้งมาก

@OneToManyควรหลีกเลี่ยงการเชื่อมโยงทิศทางเดียวเนื่องจากมีประสิทธิภาพน้อยกว่าการใช้@ManyToOneหรือการ@OneToManyเชื่อมโยงแบบสองทิศทาง

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่ดีที่สุดในการทำแผนที่@OneToManyความสัมพันธ์กับ JPA และ Hibernate ตรวจสอบบทความนี้

หนึ่งต่อหนึ่ง

ความสัมพันธ์ของตารางแบบหนึ่งต่อหนึ่งมีลักษณะดังนี้:

หนึ่งต่อหนึ่ง

ในระบบฐานข้อมูลเชิงสัมพันธ์ความสัมพันธ์แบบหนึ่งต่อหนึ่งเชื่อมโยงตารางสองตารางโดยยึดตามPrimary Keyคอลัมน์ในคอลัมน์ย่อยซึ่งเป็นการForeign Keyอ้างอิงPrimary Keyแถวของตารางแม่แถวด้วย

ดังนั้นเราสามารถพูดได้ว่าตารางลูกใช้Primary Keyร่วมกับตารางหลัก

ในแผนภาพตารางด้านบนidคอลัมน์ในpost_detailsตารางมีForeign Keyความสัมพันธ์กับคอลัมน์postตารางด้วยid Primary Key:

ALTER TABLE
    post_details
ADD CONSTRAINT
    fk_post_details_id
FOREIGN KEY (id) REFERENCES post

การใช้ JPA @OneToOneพร้อม@MapsIdหมายเหตุประกอบ

วิธีที่ดีที่สุดแมสัมพันธ์กับการใช้งาน@OneToOne @MapsIdด้วยวิธีนี้คุณไม่จำเป็นต้องมีการเชื่อมโยงแบบสองทิศทางเนื่องจากคุณสามารถดึงPostDetailsเอนทิตีได้เสมอโดยใช้Postตัวระบุเอนทิตี

การทำแผนที่มีลักษณะดังนี้:

[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") คลาสสาธารณะ PostDetails {

@Id
private Long id;

@Column(name = "created_on")
private Date createdOn;

@Column(name = "created_by")
private String createdBy;

@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
private Post post;

public PostDetails() {}

public PostDetails(String createdBy) {
    createdOn = new Date();
    this.createdBy = createdBy;
}

//Getters and setters omitted for brevity

} [/ รหัส]

วิธีนี้idคุณสมบัติทำหน้าที่เป็นทั้งคีย์หลักและคีย์ต่างประเทศ คุณจะสังเกตเห็นว่า@Idคอลัมน์ไม่ได้ใช้@GeneratedValueคำอธิบายประกอบอีกต่อไปเนื่องจากตัวระบุนั้นบรรจุด้วยตัวระบุของการpostเชื่อมโยง

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่ดีที่สุดในการทำแผนที่@OneToOneความสัมพันธ์กับ JPA และ Hibernate ตรวจสอบบทความนี้

หลายต่อหลายคน

ความสัมพันธ์ของตารางแบบหลายต่อกลุ่มมีลักษณะดังนี้:

หลายต่อหลายคน

ในระบบฐานข้อมูลเชิงสัมพันธ์ความสัมพันธ์แบบหลายต่อหลายตารางจะเชื่อมโยงสองตารางหลักผ่านตารางลูกซึ่งมีสองForeign Keyคอลัมน์ที่อ้างอิงถึงPrimary Keyคอลัมน์ของตารางหลักสองตาราง

ในแผนภาพตารางด้านบนpost_idคอลัมน์ในpost_tagตารางมีForeign Keyความสัมพันธ์กับคอลัมน์postรหัสตารางด้วยPrimary Key:

ALTER TABLE
    post_tag
ADD CONSTRAINT
    fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post

และtag_idคอลัมน์ในpost_tagตารางมีForeign Keyความสัมพันธ์กับคอลัมน์tagid ของตารางPrimary Key:

ALTER TABLE
    post_tag
ADD CONSTRAINT
    fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag

การใช้การ@ManyToManyแม็พJPA

นี่คือวิธีที่คุณสามารถแมปmany-to-manyความสัมพันธ์ของตารางกับ JPA และไฮเบอร์เนต:

@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    @GeneratedValue
    private Long id;

    private String title;

    @ManyToMany(cascade = { 
        CascadeType.PERSIST, 
        CascadeType.MERGE
    })
    @JoinTable(name = "post_tag",
        joinColumns = @JoinColumn(name = "post_id"),
        inverseJoinColumns = @JoinColumn(name = "tag_id")
    )
    private Set<Tag> tags = new HashSet<>();

    //Getters and setters ommitted for brevity

    public void addTag(Tag tag) {
        tags.add(tag);
        tag.getPosts().add(this);
    }

    public void removeTag(Tag tag) {
        tags.remove(tag);
        tag.getPosts().remove(this);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Post)) return false;
        return id != null && id.equals(((Post) o).getId());
    }

    @Override
    public int hashCode() {
        return 31;
    }
}

@Entity(name = "Tag")
@Table(name = "tag")
public class Tag {

    @Id
    @GeneratedValue
    private Long id;

    @NaturalId
    private String name;

    @ManyToMany(mappedBy = "tags")
    private Set<Post> posts = new HashSet<>();

    //Getters and setters ommitted for brevity

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Tag tag = (Tag) o;
        return Objects.equals(name, tag.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}
  1. การtagsเชื่อมโยงในPostเอนทิตีกำหนดประเภทPERSISTและMERGEเรียงซ้อนเท่านั้น ตามที่อธิบายไว้ในบทความนี้การREMOVE เปลี่ยนสถานะนิติบุคคลไม่สมเหตุสมผลสำหรับการ@ManyToManyเชื่อมโยง JPA เนื่องจากอาจทำให้เกิดการลบการเชื่อมโยงที่จะล้างทั้งสองด้านของการเชื่อมโยงในท้ายที่สุด
  2. ตามที่อธิบายไว้ใน บทความนี้วิธีการเพิ่ม / ลบยูทิลิตี้เป็นสิ่งจำเป็นถ้าคุณใช้การเชื่อมโยงแบบสองทิศทางเพื่อให้คุณสามารถตรวจสอบให้แน่ใจว่าทั้งสองด้านของการเชื่อมโยงมีการซิงค์
  3. Postนิติบุคคลใช้ระบุกิจการเพื่อความเท่าเทียมกันเพราะมันขาดที่สำคัญทางธุรกิจใด ๆ ที่ไม่ซ้ำกัน ตามที่อธิบายไว้ในบทความนี้คุณสามารถใช้ตัวระบุเอนทิตีเพื่อความเท่าเทียมกันตราบเท่าที่คุณตรวจสอบให้แน่ใจว่ามันยังคงสอดคล้องกันในการเปลี่ยนสถานะของนิติบุคคลทั้งหมดการเปลี่ยนสถานะนิติบุคคล
  4. Tagนิติบุคคลที่มีคีย์ธุรกิจที่ไม่ซ้ำกันซึ่งมีการทำเครื่องหมายกับ Hibernate เฉพาะ@NaturalIdคำอธิบายประกอบ เมื่อเป็นเช่นนั้นกุญแจธุรกิจที่เป็นเอกลักษณ์ก็คือผู้สมัครที่ดีที่สุดสำหรับการตรวจสอบความเท่าเทียมกัน
  5. mappedByแอตทริบิวต์ของpostsสมาคมในTagเครื่องหมายนิติบุคคลที่ในความสัมพันธ์แบบสองทิศทางนี้Postนิติบุคคลเป็นเจ้าของสมาคม สิ่งนี้จำเป็นเนื่องจากมีเพียงด้านเดียวเท่านั้นที่สามารถเป็นเจ้าของความสัมพันธ์ได้และการเปลี่ยนแปลงจะแพร่กระจายไปยังฐานข้อมูลจากด้านเฉพาะนี้เท่านั้น
  6. Setคือการเป็นที่ต้องการเช่นใช้Listกับ@ManyToManyมีประสิทธิภาพน้อย

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่ดีที่สุดในการทำแผนที่@ManyToManyความสัมพันธ์กับ JPA และ Hibernate ตรวจสอบบทความนี้


1

สิ่งนี้อาจเรียกร้องให้มีเรือหลายลำที่สัมพันธ์กันดังนี้



public class Person{

    private Long personId;
    @manytomany

    private Set skills;
    //Getters and setters
}

public class Skill{
    private Long skillId;
    private String skillName;
    @manyToMany(MappedBy="skills,targetClass="Person")
    private Set persons; // (people would not be a good convenion)
    //Getters and setters
}

คุณอาจต้องกำหนด joinTable + JoinColumn แต่มันจะทำงานได้โดยไม่ต้อง ...


1

ฉันจะอธิบายอย่างนั้น:

OneToOne -ความสัมพันธ์OneToOne

@OneToOne
Person person;

@OneToOne
Nose nose;

OneToMany - ManyToOneสัมพันธ์

@OneToMany
Shepherd> shepherd;

@ManyToOne
List<Sheep> sheeps;

ManyToMany -ความสัมพันธ์ManyToMany

@ManyToMany
List<Traveler> travelers;

@ManyToMany
List<Destination> destinations;

0

ก่อนอื่นให้อ่านการปรับละเอียดทั้งหมด โปรดทราบว่า NHibernate (ดังนั้นฉันถือว่า Hibernate ด้วย) การทำแผนที่เชิงสัมพันธ์มีความสอดคล้องตลกกับ DB และการทำแผนที่กราฟวัตถุ ตัวอย่างเช่นความสัมพันธ์แบบหนึ่งต่อหนึ่งมักจะนำมาใช้เป็นความสัมพันธ์แบบหนึ่งต่อหนึ่ง

ประการที่สองก่อนที่เราจะบอกคุณว่าคุณควรเขียนแผนที่ O / R ของคุณอย่างไรเราต้องดูฐานข้อมูลของคุณด้วย โดยเฉพาะอย่างยิ่งความสามารถทักษะเดียวสามารถครอบครองโดยหลายคน ถ้าเป็นเช่นนั้นคุณมีความสัมพันธ์แบบหลายต่อหลายคน มิฉะนั้นจะเป็นแบบตัวต่อตัว

ประการที่สามฉันไม่ต้องการใช้ความสัมพันธ์แบบหลายต่อหลายคนโดยตรง แต่แทนที่จะสร้างโมเดล "ตารางเข้าร่วม" ในรูปแบบโดเมนของคุณ - กล่าวคือถือว่าเป็นเอนทิตีเช่นนี้

class PersonSkill 
{
    Person person;
    Skill skill;    
}

จากนั้นคุณเห็นสิ่งที่คุณมี? คุณมีความสัมพันธ์แบบหนึ่งต่อหลายสองคน (ในกรณีนี้บุคคลอาจมีการรวบรวม PersonSkills แต่จะไม่มีชุดทักษะ) อย่างไรก็ตามบางคนอาจต้องการใช้ความสัมพันธ์แบบหลายต่อหลายคน (ระหว่างบุคคลและทักษะ) นี่คือความขัดแย้ง

ประการที่สี่หากคุณมีความสัมพันธ์แบบสองทิศทาง (เช่นไม่เพียง แต่บุคคลจะมีชุดทักษะ แต่ยังทักษะมีกลุ่มบุคคล) NHibernate ไม่บังคับใช้แบบสองทิศทางใน BL ของคุณสำหรับคุณ; มันเข้าใจเฉพาะทิศทางของความสัมพันธ์เพื่อจุดประสงค์ในการติดตาเท่านั้น

ประการที่ห้าหลายต่อหลายคนใช้งานง่ายขึ้นอย่างถูกต้องใน NHibernate (และฉันถือว่า Hibernate) มากกว่าหนึ่งต่อหลายคน (การทำแผนที่คอลเลกชัน)

โชคดี!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.