티스토리 뷰

JPA

연관관계

토마토계란 2023. 6. 20. 23:17
Member                         Team
---                            ---
id                             id
team_id                        name
username
  • 객체와 테이블 연관관계 정리

    • 객체참조로 연관관계를 맺는다
    • 테이블외래키로 연관관계를 맺는다
    • 객체는 양방향으로 연관관계를 설정할 수 없다. 양쪽에 설정한다고 해도 서로 다른 단방향 관계 2개인 것이다.
  • 어노테이션 사용

    • 연관관계 매핑 시 다중성을 나타내는 어노테이션 사용 필수

      • @ManyToOne, OneToMany, OneToOne

        attribute feature default value
        optional false 로 설정하면 연관된 엔티티가 항상 존재해야 한다. Inner Join true
        fetch 글로벌 페치 전략 설정 - @ManyToOne : EAGER
      • @OneToMany : LAZY |
        | cascade | 영속성 전이 기능 | |
        | targetEntity | 연관된 엔티티의 타입 정보 설정.
        거의 사용하지 않는다. deprecated?
        컬렉션을 사용해도 제네릭으로 타입 정보를 알 수 있다. | |

    • @JoinColumn

      • 외래 키를 매핑할 때 사용. 생략 가능

        attribute feature default value
        name 매핑할 외래 키 컬럼명 {필드명}_{참조하는 테이블의 기본 키 컬럼명}
        referencedColumnName 외래 키가 참조하는 대상 테이블의 컬럼명 참조하는 테이블의 기본키 컬렴명
        foreignKey(DDL) 외래 키 제약조건을 직접 지정할 수 있다.
        이 속상은 테이블을 생성할 때만 사용
        unique
        nullable
        insertable
        updatable
        columnDefinition
        table @Column 과 같다
  • 단방향

    • 다대일 N:1

      • 일대일 관계와 유사. 어떤 걸 사용할지는 반대편 관계가 일대다인지 일대일인지를 보면 된다

      • 코드

          @Entity
          public class Member {
            @Id
            private String id;
            private String username;
        
            // 연관관계 매핑
            @ManyToOne
            @JoinColumn(name = "team_id")
            private Team team;
        
            // 연관관계 설정
            public void setTeam(Team team) {this.team = team;}
          }
        
          @Entity
          public class Team {
            @Id private String id;
            private String name;
          }
  • 양방향

    • 다대일

      • 코드

          @Entity
          public class Member {
            @Id
            private String id;
            private String username;
        
            // 연관관계 매핑
            @ManyToOne
            @JoinColumn(name = "team_id")
            private Team team;
        
            // 연관관계 설정
            public void setTeam(Team team) {this.team = team;}
          }
        
          @Entity
          public class Team {
            @Id private String id;
            private String name;
        
            // 연관관계 매핑. mappedBy : 반대쪽 매핑된 필드 이름
            @OneToMany(mappedBy = "team")
            private List<Member> members = new ArrayList<Member>();
          }
    • 연관관계 주인

      • 테이블과 달리 객체로 양방향 연관관계를 설정하면 관리 포인트가 두 곳이 된다.
      • 따라서 테이블의 외래 키를 관리할 객체를 정해야 한다. 이를 연관관계의 주인이라 한다.
      • 주인 객체가 외래키 등록, 수정, 삭제가 가능하고, 주인 객체가 아니면 읽기만 가능하다
      • mappedBy 속성을 사용하지 않는 객체가 주인 객체이다.
      • 주인은 테이블에 외래키가 있는 곳으로 정해야 한다.
    • 주의점

      • 연관관계의 주인인 곳에는 값을 입력하지 않고, 주인이 아닌 객체에만 값을 입력하는 것을 주의해야 한다.

        그러나 순수 객체 관점에서 보면 둘다 값을 입력해주는 것이 좋다.

      • 무한 루프에 빠지지 않게 조심해야 한다. toString() 같은 메서드나 JSON 으로 변환할 때 발생 가능하다.

    • 결론

      • 객체에서 양방향 연관관계를 사용하려면 로직을 견고하게 작성해야 한다.
      • 양방향의 장점은 객체 그래프 탐색 기능이 추가된 것 뿐이다.
  • 조인 테이블

    • 조인 컬럼이 아닌 테이블로 두 테이블을 연결하는 방법이 있다

      Parent                 parent_child                 Child

    id parent_id(pk, fk) id
    name child_id(unq, fk) name
    username

    
      - 일대일
          - 조인 테이블의 외래키 컬럼 각각에 유니크 인덱스를 설정해야 한다
          - 코드
    
              ```java
              @Entity
              public class Parent {
                @Id
                private String id;
                private String name;
    
                // 연관관계 매핑
                @OneToOne
                @JoinTable(name = "parent_child",
                                      joinColumns = @JoinColumn(name = "parent_id),
                                      inverseJoinColumns = @JoinColumn(name = "child_id)
              )
                private Child child;
    
              }
    
              @Entity
              public class Child {
                @Id private String id;
                private String name;
    
                // 양방향으로 하려면 설정
                @OneToOne(mappedBy = "child")
                private Parent parent;
              }
              ```
    
    
- 일대다
    - 다 에 해당하는 컬럼에 유니크 인덱스를 설정해야 한다 (여기서는 child_id)
    - 코드

        ```java
        @Entity
        public class Parent {
          @Id @GeneratedValue
          private String id;
          private String name;

          // 연관관계 매핑
          @OneToMany
          @JoinTable(name = "parent_child",
                                joinColumns = @JoinColumn(name = "parent_id),
                                inverseJoinColumns = @JoinColumn(name = "child_id)
        )
          private List<Child> child = new ArrayList<Child>();

        }

        @Entity
        public class Child {
          @Id @GeneratedValue
          private String id;
          private String name;

          // 양방향으로 하려면 설정
          @ManyToOne(mappedBy = "child")
          private Parent parent;
        }
        ```

- 다대일
    - 다 에 해당하는 컬럼에 유니크 인덱스를 설정해야 한다 (여기서는 child_id)
    - 코드

        ```java
        @Entity
        public class Parent {
          @Id @GeneratedValue
          private String id;
          private String name;

          // 양방향으로 하려면 설정
          @OneToMany(mappedBy = "parent")
          private List<Child> child = new ArrayList<Child>();

        }

        @Entity
        public class Child {
          @Id @GeneratedValue
          private String id;
          private String name;

          // 연관관계 매핑
          @ManyToOne(optional = false)
          @JoinTable(name = "parent_child",
                                joinColumns = @JoinColumn(name = "child_id),
                                inverseJoinColumns = @JoinColumn(name = "parent_id)
        )
          private Parent parent;
        }
        ```

- 다대다
    - 두 컬럼을 같이 복합 유니크 제약조건을 걸어야 한다.
    - 조인 테이블에 외래키 이외의 새로운 컬럼을 추가하면 @JoinTable 을 사용할 수 없다.
    대신 새로운 엔티티를 만들어서 매핑해야 한다
    - 코드

        ```java
        @Entity
        public class Parent {
          @Id @GeneratedValue
          private String id;
          private String name;

          // 연관관계 매핑
          @ManyToMany
          @JoinTable(name = "parent_child",
                                joinColumns = @JoinColumn(name = "child_id),
                                inverseJoinColumns = @JoinColumn(name = "parent_id)
        )
          private List<Child> child = new ArrayList<Child>();

        }

        @Entity
        public class Child {
          @Id @GeneratedValue
          private String id;
          private String name;
        }
        ```

'JPA' 카테고리의 다른 글

[QueryDSL] fetchResults()가 deprecated 된 이유  (0) 2024.02.26
JPA (1) - JPA 란?  (0) 2021.12.22
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함