일대 다, 다 대일, 다 대다의 차이점은 무엇입니까?


144

좋아, 이것은 아마도 사소한 질문 일지 모르지만 차이점과 각각의 사용 시점을 시각화하고 이해하는 데 어려움을 겪고 있습니다. 또한 단방향 및 양방향 매핑과 같은 개념이 일대 다 / 다 대다 관계에 어떤 영향을 미치는지에 대해서는 약간 불분명합니다. 지금은 최대 절전 모드를 사용하고 있으므로 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

일대 다 : 한 사람이 많은 기술을 가지고 있으며, 사람간에 기술이 재사용되지 않습니다

  • 단방향 : 사람은 세트를 통해 기술을 직접 참조 할 수 있습니다
  • 양방향 : 각 "자식"스킬에는 Person에 대한 단일 포인터가 있습니다 (코드에는 표시되지 않음).

다 대다 : 한 사람이 많은 기술을 가지고 있으며, 기술은 사람 사이에서 재사용됩니다.

  • 단방향 : 사람은 세트를 통해 기술을 직접 참조 할 수 있습니다
  • 양방향 (Bidirectional) : 스킬에는 관련된 일련의 인물이 있습니다.

일대 다 관계에서 하나의 개체는 "부모"이고 다른 하나는 "자식"입니다. 부모는 자녀의 존재를 통제합니다. 다 대다에서 두 가지 유형의 존재는 두 가지 유형 이외의 것 (더 큰 응용 프로그램 컨텍스트에서)에 의존합니다.

귀하의 주제 (도메인)는 관계가 일대 다 또는 다 대다인지 여부를 지시해야하지만 단방향 또는 양방향 관계를 만드는 것은 메모리, 처리, 성능을 절충하는 공학적 결정이라는 것을 알았습니다. 등

혼동 될 수있는 것은 다 대다 양방향 관계가 대칭 일 필요는 없다는 것입니다! 즉, 많은 사람들이 기술을 가리킬 수 있지만 기술은 그 사람들과 관련 될 필요는 없습니다. 일반적으로 그러하지 만 그러한 대칭은 필수 사항이 아닙니다. 예를 들어 사랑을 가져 오십시오. 양방향 ( "I-Love", "Loves-Me")이지만 종종 비대칭 적입니다 ( "나는 그녀를 사랑하지만 그녀는 나를 사랑하지 않습니다")!

이것들은 모두 Hibernate와 JPA에 의해 잘 지원됩니다. Hibernate 또는 다른 ORM은 양방향 다 대다 관계를 관리 할 때 대칭을 유지하는 것에 대한 전리품을 제공하지 않는다는 것을 기억하십시오.


명확히하기 위해, 관계는 BL 또는 O / R 매핑에서 (단독 히 서로 독립적으로) 단방향 또는 양방향 일 수 있습니다.
jyoungdev

4
"LOVE"예제가 방금 명확 해졌습니다. ManyToMany는 내 유형의 매핑입니다.
압둘라 칸

1
감독자. 이것은 그것을 잘 설명하고 (그리고 OP의 예와 관련하여)
Anupam

1
질문에 제대로 대답하지 않습니다. 당신은 많은 부분을 그리워합니다. 일대 다 및 다대 일은 인식의 문제이지만이 대답은 그것을 언급하지 않습니다.
Manzur Alahi

249

모든 사람처럼 보인다는 응답되어 One-to-many대를 Many-to-many:

차이 One-to-many, Many-to-oneMany-to-Many이다 :

One-to-manyvs Many-to-one는 관점의 문제입니다 . Unidirectionalvs Bidirectional는 매핑에 영향을 미치지 않지만 데이터에 액세스하는 방법에 차이를 만듭니다.

  • 에서 측면의 기준 유지할 측면을. 좋은 예는 "국가에는 도시가있다"입니다. 이 경우 한면이며 많은면입니다. 테이블에 열이 있습니다 .Many-to-onemanyoneStateCitystate_idcities

에서 단방향 , Person클래스는있을 것이다 List<Skill> skills하지만 Skill필요가 없습니다 Person person. 에서 양방향 모두 속성이 추가되고 그것은 당신이 액세스 할 수 있도록 Person스킬 (즉, 주어진 skill.person).

  • 에서는 One-to-Many일측 기준 우리의 포인트가 될 것이다. 예를 들어 "사용자에게 주소가 있습니다". 이 경우 우리는 세 개의 열이있을 수 있습니다 address_1_id, address_2_id그리고 address_3_id또는 테이블까지 살펴 고유의 제약 조건 user_id등을 address_id.

에서 단방향 , a는 User것입니다 Address address. 양방향 수업 이 추가 List<User> users됩니다 Address.

  • 에서 Many-to-Many각 당사자의 구성원 상대방의 회원 임의의 수에 대한 참조를 보유 할 수 있습니다. 이를 위해 조회 테이블 이 사용됩니다. 이에 대한 예는 의사와 환자의 관계입니다. 의사는 많은 환자를 가질 수 있으며 그 반대도 마찬가지입니다.

27
이 답변은 허용되는 답변이어야하며, 대부분의 다른 답변은 질문을 놓칩니다.
arg20

첫 번째 예가 잘못되었습니다. A Person이 있고 Person with Skills가 @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

"일"쪽의 의미로 일대 다와 다 대일을 구별합니다. 두 예에서 "사용자"는 가장 중요한 엔티티입니다. 그것은 "하나"에 때 그래서 (사용자 및 기술 skillsperson_id당신이 많은 한 -에 -이 전화를하지만 하나의 "다"쪽 (사용자와 주소, 때) users이를 address_id) 다음 호출 대일. 그러나 구조적으로 두 경우 모두 동일하며 일대 다라고합니다.
mixel

38

1) 원은 엔티티 / POJO / Bean입니다

2) deg는 그래프 (가장자리 수)와 같은 정도의 약어입니다.

PK = 기본 키, FK = 외국 키

정도와 측면 이름 사이의 모순에 유의하십시오. 다수는 차수 = 1에 해당하고 1은 차수> 1에 해당합니다.

일대 다 다 대일의 그림


1
객체 그래프를 양방향으로 테이블에 묶는 방법을 정말 좋아합니다.
Dmitry Minkovsky

3
봐 바보,이 얼마나 프로그래머의 필기 과 같다 : 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 one롤 루트?
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@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두 가지 유틸리티 방법 (예 : addCommentremoveComment)을 제공합니다. 양방향 연관 작업을 수행 할 때마다 항상 이러한 방법을 제공해야합니다. 그렇지 않으면 매우 미묘한 상태 전파 문제가 발생할 수 있습니다 .

단방향 @OneToMany연결은 @ManyToOne양방향 @OneToMany연결을 사용 하는 것보다 비효율적이므로 피해야합니다 .

@OneToManyJPA 및 Hibernate와의 관계 를 맵핑하는 가장 좋은 방법에 대한 자세한 내용은 이 기사를 확인 하십시오 .

1-1

일대일 테이블 관계는 다음과 같습니다.

1-1

관계형 데이터베이스 시스템에서 일대일 테이블 관계 는 상위 테이블 행 Primary KeyForeign 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

주석 @OneToOne과 함께 JPA 사용@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연결.

@OneToOneJPA 및 Hibernate와의 관계 를 맵핑하는 가장 좋은 방법에 대한 자세한 내용은 이 기사를 확인 하십시오 .

다 대다

다 대다 테이블 관계는 다음과 같습니다.

다 대다

관계형 데이터베이스 시스템에서 다 대다 테이블 관계는 두 개의 상위 테이블의 Foreign Key열을 참조하는 두 개의 열 을 포함하는 하위 테이블을 통해 두 개의 상위 테이블을 연결합니다 Primary Key.

위의 테이블 다이어그램에서 테이블의 post_id열 은 테이블 ID 열과 관계 post_tag가 있습니다 .Foreign KeypostPrimary Key

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

그리고 테이블 의 tag_id열 은 테이블 ID 열과 관계가 있습니다 .post_tagForeign KeytagPrimary Key

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

JPA @ManyToMany매핑 사용

다음은 many-to-manyJPA 및 Hibernate와 테이블 관계를 맵핑하는 방법입니다 .

@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연결 PostPERSISTMERGE캐스케이드 유형 만 정의합니다 . 설명한 바와 같이 ,이 기사REMOVE 엔티티의 상태 천이는 A에 대한 어떠한 의미하지 않는다 @ManyToMany궁극적 연관 양쪽 닦아 것이다 연쇄 삭제를 실행할 수 있기 때문에 JPA 협회.
  2. 이 기사 에서 설명한대로 양방향 연관을 사용하는 경우 추가 / 제거 유틸리티 메소드는 필수이므로 연관의 양쪽이 동기화되었는지 확인할 수 있습니다.
  3. Post는 고유 한 비즈니스 키가 부족하기 때문에 기업은 평등에 대한 개체 식별자를 사용합니다. 이 기사 에서 설명한대로 모든 엔티티 상태 전이에서 일관성을 유지하는 한 엔티티 식별자를 동등하게 사용할 수 있습니다 .
  4. Tag기업은 최대 절전 모드 별의 표시하는 고유 한 비즈니스 키가 @NaturalId주석을. 이 경우 고유 한 비즈니스 키가 동등성 검사에 가장 적합한 후보입니다 .
  5. mappedBy의 속성 posts에 연관 Tag이 양방향 관계 엔티티 마크 Post엔티티가 관계를 소유하고있다. 한 쪽만 관계를 소유 할 수 있으므로 변경이이 특정 쪽에서 데이터베이스로만 전파되기 때문에이 작업이 필요합니다.
  6. Set사용 a 같이 선호된다 List으로 @ManyToMany덜 효율적이다.

@ManyToManyJPA 및 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 맵 작성 방법을 알려 드리기 전에 DB도 확인해야합니다. 특히 단일 스킬을 여러 사람이 소유 할 수 있습니까? 그렇다면 다 대다 관계입니다. 그렇지 않으면 다 대일입니다.

셋째, 다 대다 관계를 직접 구현하는 대신 도메인 모델에서 "조인 테이블"을 모델링합니다. 즉, 다음과 같이 엔터티로 취급합니다.

class PersonSkill 
{
    Person person;
    Skill skill;    
}

그렇다면 당신은 무엇을 볼 수 있습니까? 두 개의 일대 다 관계가 있습니다. (이 경우 Person은 PersonSkills 모음을 보유 할 수 있지만 Skills 모음을 보유하지는 않습니다.) 그러나 일부는 다 대다 관계 (Person과 Skill 간)를 선호합니다. 이것은 논쟁의 여지가 있습니다.

넷째, 양방향 관계가있는 경우 (예를 들어, Person에는 스킬 모음이있을뿐만 아니라 Skill에는 Person 모음이 있음) NHibernate는 BL에 양방향성을 적용 하지 않습니다 . 지속성 목적을위한 관계의 양방향성 만 이해합니다.

다섯째, 다대 일은 일대 다 (컬렉션 매핑)보다 NHibernate (및 Hibernate라고 가정)에서 올바르게 사용하기가 훨씬 쉽습니다.

행운을 빕니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.