본문 바로가기
카테고리 없음

DB 엔티티 연관관계

by 2nyong 2023. 4. 17.

단방향 연관관계

  • @ManyToOne
  • 아래 예시 코드에서 Many는 Member(테이블명)이고, One은 Team(컬럼명)이다.
  • '하나의 Team에 여러명의 Member가 있다' 로 이해할 수 있다.
@Entity
@Getter
@Setter
public class Member {
	@Id
	@Column(name = "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
@Getter
@Setter
public class Team {
	@Id
	@Column (name = "TEAM_ID")
	private String id;
	
	private String name;
}

양방향 연관관계

연관관계 설명을 위해 배달주문 애플리케이션을 가정해 3개의 엔티티를 예시로 사용하겠다.

  1. Member : 사용자
  2. Orders : 주문 내역
  3. Food : 주문할 수 있는 음식

 

  • Member 엔티티
@Getter
@Entity
@NoArgsConstructor
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
	
    @Column(nullable = false)
    private String memberName;

    @OneToMany(mappedBy = "member", fetch = FetchType.EAGER)
    private List<Orders> orders = new ArrayList<>();

    public Member(String memberName) {
        this.memberName = memberName;
    }
}
  • Member 엔티티(테이블)의 orders 필드(컬럼)
    - 사용자(Member)는 여러번 주문(orders)할 수 있으므로, @OneToMany 연관관계를 갖는다.

  • Orders 엔티티
@Getter
@Entity
@NoArgsConstructor
public class Orders {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "food_id")
    private Food food;

    @ManyToOne
    @JoinColumn(name = "member_id")
    private Member member;

    public Orders(Food food, Member member) {
        this.food = food;
        this.member = member;
    }
}
  • Orders 엔티티(테이블)의 food 필드(컬럼)와 member 필드(컬럼)
    - 주문(Orders) 한건에 음식(food) 한가지와 주문한 사람(member) 한명을 포함할 수 있으므로 @ManyToOne 연관관계
      를 갖는다.

  • Food 엔티티
@Getter
@Entity
@NoArgsConstructor
public class Food {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String foodName;
    
    @Column(nullable = false)
    private int price;

    @OneToMany(mappedBy = "food",fetch = FetchType.EAGER)
    private List<Orders> orders = new ArrayList<>();

    public Food(String foodName, int price) {
        this.foodName = foodName;
        this.price = price;
    }
}
  • Food 엔티티(테이블)의 orders 필드(컬럼)
    - 하나의 음식(Food)는 여러번 주문(orders)될 수 있으므로, @OneToMany 연관관계를 갖는다.

 

- 양방향 연관관계 Many 쪽에서 살펴보기

// Member의 Team쪽 (단방향 연관관계 예시 코드)
@ManyToOne
@JoinColumn(name="team_id")
private Team team;

// Orders의 Member쪽 (양방향 연관관계 예시 코드 중 Orders 엔티티)
@ManyToOne
@JoinColumn(name=" member_id")
private Member member;
  • Many의 경우 단방향과 양방향 모두 코드 작성에서 차이가 없으며, 기본적으로 DB의 외래키는 양방향에서 조회가 가능하기 때문에 DB 상에서도 차이가 없다.

 

- 양방향 연관관계 Many 반대쪽에서 살펴보기

// Member의 Orders 쪽 (양방향 연관관계 예시)
@OneToMany(mappedBy = "member", fetch = FetchType.EAGER) // 단방향에는 없던 어노테이션!
private List<Orders> orders = new ArrayList<>();
  • 사실 객체에는 양방향 연관관계라는 것이 없으며, 서로 다른 단방향 연관관계를 잘 묶어 양방향으로 보이게 한 것이다.
    - Member 엔티티에 Orders 엔티티의 주소값을, Orders 엔티티에 Member 엔티티의 주소값을 가지고 있는 것이다.
  • 그러나 외래키(FK)는 양방향 연관관계를 갖는 두 개의 엔티티 중 하나의 엔티티만 가지면 된다.
  • 외래키를 관리하는 엔티티를 연관관계의 주인이라고 하며, 연관관계의 주인만이 DB 연관관계와 매핑되고 외래키를 관리(등록, 수정, 삭제)할 수 있다.
    - 주인이 아닌 엔티티는 읽기만 가능하다.
  • 연관관계의 주인은 mappedBy를 통해 이루어지며, 연관관계의 주인을 정함으로써 외래키와 관리자를 선택할 수 있다.

댓글