일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 종료코드
- chroot exit code
- openjdk
- SpringBoot 2.0
- OracleJDK
- ManyToMany
- JPA
- SpringBoot
- OneToMany
- Multi Datasource
- ManyToOne
- Entity
- 트랜잭션 쓰기 지연
- 다중 트랜잭션
- OneToOne
- 다중 데이타소스
- 디자인 패턴
- docker
- 활성프로브
- Design Pattern
- dirty check
- Multi Transaction
- mybatis
- JDK
- MaxRAMPercentage
- exit code
- 영속화
- Java
- K8s
- 변경 감지
- Today
- Total
조금 평범한 개발 이야기
JPA 관계와 그 사용법에 대해 (양방향) 본문
데이타베이스에서 테이블간의 관계를 구성하는 방법은 OneToOne, OneToMany, ManyToOne, ManyToMany 가 있습니다. 테이블간의 관계에서는 단방향과 양방향에 대한 구분이 없지만 JPA 상에서는 사용하는 Entity 에 따른 차이가 존재합니다. 단방향은 FK (Foreign Key) 를 소유한 Entity 에서 대상 Entity 를 참조하는 방식이며 양방향은 FK 를 소유한 Entity 와 대상 Entity 에서 서로가 서로를 참조할 수 있는 방식입니다.
양방향 관계를 지정할때 유의해야 할 점은 서로의 Entity 데이타에 대해 동일한 사용 권한을 가지기 때문에 의도치 않은 데이타의 오염이 일어 날 수 있다는 점 입니다. Entity 의 값이 변경 되었는데 이게 누구에 의한 데이타의 변경인지 파악하기 어려워 진다는 겁니다. 그래서 프로그램을 개발할때 데이타의 변경에는 최대한 폐쇄적으로 접근하는게 좋기 때문에 가급적이면 양방향의 관계는 사용하지 않는 것이 좋습니다.
@OneToOne
앞서 단방향 @OneToOne 관계를 설명하면서 FK 를 소유한 자식 Entity 가 부모 Entity 를 참조하는 형태에 대해서 살펴 보았습니다. 양방향 @OneToOne 은 이와 크게 다르지 않으며 부모 Entity 에서 자식 Entity 에 대한 mappedBy 설정만 추가하면 됩니다. 이때 mappedBy 설정에는 자식 Entity 에서 바라보는 부모 Entity 의 변수이름을 지정합니다.
@Entity(name = "parent")
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(mappedBy = "parent") // Child Entity 에서 변수로 사용하고 있는 parent 이름
private Child child;
}
@Entity(name = "child")
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
@JoinColumn(name = "parent_id")
private Parent parent;
}
@OneToMany, @ManyToOne
@OneToMany, @ManyToOne 은 사용되는 Entity 가 누구냐에 따라 달라지는 것이지 원래는 데이타베이스 상에서 같은 관계를 의미합니다. 부모 Entity 에서는 @OneToMany, 자식 Entity 에서는 @ManyToOne 이 되는 것 입니다. 그렇기 때문에 양방향으로 @OneToMany 를 사용하면 자식 Entity 에는 @ManyToOne 이 같이 사용 됩니다.
앞서 단방향 @OneToMany 일 경우 관계 중 유일하게 FK 가 위치한 자식 Entity 가 아닌 부모 Entity 에 어노테이션이 정의된다고 이야기 드렸습니다. 양방향 @OneToMany 일때는 부모 Entity 에 @JoinColumn 어노테이션이 제거되고 @OneToMany 의 mappedBy 속성을 추가해 자식 Entity 와의 관계를 설정합니다. 이때 mappedBy 속성에는 자식 Entity 에서 부모 Entity를 바라보는 변수이름을 지정합니다. 자식 Entity 에서는 단방향 @ManyToOne 와 동일하게 부모와의 관계를 지정해 줍니다.
@Entity(name = "parent")
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "parent")
private List<Child> childList;
}
@Entity(name = "child")
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "parent_id")
private Parent parent;
}
@ManyToMany
단방향 @ManyToMany 는 앞서 물리적으로는 존재할 수 없는 논리적인 관계이며 이를 위해 중간에 서로의 PK 정보를 담아두는 맵핑 테이블을 사용해 @ManyToMany 를 표현한다고 이야기 드렸습니다. 양방향 @ManyToMany 는 이와 크게 다르지 않지만 문제는 서로의 Entity 가 동등한 위치를 가지고 있기 때문에 관계 설정 정보를 어디에 지정할 것 인가를 결정해야 한다는 점 입니다. 관계 설정 정보를 둘중 어디에 둘 것인지를 결정 했다면 반대쪽 Entity 에 @ManyToMany 어노테이션을 정의하고 mappedBy 속성에 정의된 변수이름을 지정합니다.
@Entity(name = "parent")
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany
@JoinTable(
name = "parent_child",
joinColumns = @JoinColumn(name = "parent_id"),
inverseJoinColumns = @JoinColumn(name = "child_id")
)
private List<Child> childList;
}
@Entity(name = "child")
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(mappedBy = "childList") // 반대쪽에 정의된 변수이름으로 관계를 지정
private Parent parent;
}
관계를 설정하기에 앞서
JPA 에서 Entity 간의 관계를 지정할때 주의해야 될 점은 Entity 객체의 모든 관계에 대해서 설정을 하겠다고 생각을 하지 않아야 한다는 점 입니다. 물론 논리적으로 완벽하게 데이타베이스상의 모든 관계를 정의하고 싶다는 욕심이 들더라도 이것은 의도치 않은 데이타 오용을 막고 불필요한 부하가 증가되어 시스템의 전반적인 속도가 느려지는 현상을 막을 수 있습니다.
관계를 설정하기전 반드시 이 관계가 시스템상에서 꼭 논리적으로 결합되어야 하는지에 대해 생각해봐야 합니다. 구분하기 위한 적절한 기준은 이 Entity 객체가 혼자 독립적으로 데이타 조작이 되는지 여부 입니다. 만약 단일 Entity 가 다른 Entity 와 연관이 없이 CRUD 가 모두 동작이 된다면 이는 독립적인 Entity 일 확률이 아주 높습니다. 만약 이에 대해 정확한 답을 내릴 수 없다면 두 Entity 객체 사이에 관계를 설정하지 않고 데이타의 Key 를 이용해 값을 참조 하는 방법을 사용해야 하는 것이 좋습니다.
다음글에서는 Repository 를 이용한 값의 조회에 대해서 알아 보겠습니다.
'개발 > 쉽게 이해하고 사용하는 JPA' 카테고리의 다른 글
JPA 환경에서 MyBatis 를 사용하여 데이타를 가지고 오기 (0) | 2018.10.22 |
---|---|
JPA Repository 를 이용한 데이타 사용 (1) | 2018.10.17 |
JPA 관계와 그 사용법에 대해 (단방향) (4) | 2018.10.09 |
JPA 기본 사용 문법 파악하기 (0) | 2018.10.01 |
JPA 개요와 Spring Boot 개발 환경구성 (0) | 2018.09.17 |