-
[JPA] 값 타입인프런 - 스프링/JPA 프로그래밍 - 기본편 2023. 11. 30. 23:27
- 이러한 자바 기능 덕분에 side effect 없이 값들을 안전하게 사용할 수 있다.
- 임베디드 타입을 사용하면 테이블에 저장되는 것은 동일하지만 객체지향스럽게 코드를 작성할 수 있게 된다.
예제 코드
- 임베디드 타입도 결국 테이블 컬럼들의 모음이기 때문에 테이블에서 외래키를 필드로 가질 수 있듯이 임베디드 타입도 엔티티를 가지고 연관관계를 맺을 수 있으며 또 다른 임베디드 타입도 가질 수 있다.
예제 코드
- 이렇게 작성하게 되면 Address 안의 city, street, zipcode 필드가 중복되게 되어 에러가 발생한다.
결과 쿼리
애너테이션 관련 꿀팁
- 해당 애너테이션에 들어가서 애너테이션 명에 마우스를 올리면 위와 같이 예제를 통한 사용법을 알려준다.
예제 코드
일반 클래스에서 equals를 오버라이딩 하는 과정에서의 두 가지 옵션
1. 파라미터로 하위타입을 허용하는가
- 이 경우에 equals 메서드의 형태가 instanceOf를 사용하는 방식으로 조금 바뀌고 상속 관계에 있는 다른 클래스들이 equals 메서드를 사용하는데에 제약이 생길 수 있다.
2. getter를 사용할 것인가
- 프록시를 사용하는 경우 getter를 사용해서 오버라이딩 해야한다.
- 값 타입 컬렉션은 값 타입이 하나 이상일때 사용한다.
- 테이블이 따로 만들어지는 형태이긴 하지만 엔티티와의 차이점은 따로 Id 값을 PK로 갖는 것이 아니라 전체 컬럼을 PK로 가지는 점이다.
예제 코드
- @CollectionTable의 joinColums와 @JoinColumn을 이용하여 매핑되는 FK의 이름을 설정할 수 있다.
- 또한 @Column을 이용하여 필드명을 변경할 수도 있다.(List<Address>의 경우에는 @AttributeOverrides와 @AttributeOverride를 이용하여 필드명들을 변경할 수 있다.)
- @CollectionTable은 필수 애너테이션은 아니다.
- 값 타입은 수정하는 것이 아니라 완전히 갈아끼워넣는다는 개념을 이용해야 side effect가 발생하지 않는다.(공유하면 안됨.)
기본 값 타입 컬렉션의 경우
- 따라서 이런식으로 컬렉션에서 직접 찾아서 지우고 새로운 것을 넣어줘야 한다. 이때 위와 같이 컬렉션만 수정해도 영속성 전이가 일어나게 된다.
임베디드 타입의 값 타입 컬렉션의 경우
- 기본 값 타입 컬렉션의 경우와 동일하게 컬렉션에서 기존의 것을 지우고 새로운 것을 넣어주는 과정은 동일하지만 이때에는 임베디드 타입인 Address에 equals 메서드가 반드시 오버라이딩되어 있어야 한다. 그 이유는 컬렉션의 remove 메서드가 제거할 객체를 찾을때 equals 메서드를 사용하기 때문이다.
여기서 주의할점!!
위와 같이 Address를 한 개 지우고 한 개를 추가하였을 때 실제 쿼리는 해당 회원에 관련된 Address를 모두 지우고 remove한 Address를 제외하고 나머지 Address들에 대한 insert 쿼리가 날라가게 된다. 정확하게는 컬렉션에 남아 있는 Address들을 다시 모두 insert 해주는 방식이다.(원하는 결과지만 예상한 동작은 아님) - 그 이유는 값 타입은 엔티티와 다르게 식별자 개념이 없어 값이 변경되면 추적이 어렵기 때문이다. 즉, 원하는 값만 변경하기 어려움.
java.util.ArrayList의 remove 메서드
- 3번째 사항은 위의 주의할점에서 언급한 내용이다. 따라서 주인 엔티티와 연관된 데이터가 만약에 100만 개이고 거기서 1개만 변경하는 경우에 엄청난 비효율이 일어날 수 있기에 가급적 사용을 지양해야한다.
값 타입 컬렉션 대안 예제 코드
- 일대다 단방향 매핑으로 풀어내고 영속성 전이와 고아 객체 제거를 통해 값 타입 컬렉션과 동일하게 부모 엔티티가 생명주기를 관리하게 한다.(여기서 mappedBy 속성을 사용하지 않고 @JoinColumn을 사용하여 연관관계의 주인을 1쪽에 두었다.)
- 일대다 단방향 매핑을 하게 되면 외래키의 위치와 연관관계 주인의 위치가 달라서 update 쿼리가 추가적으로 나갈수밖에 없다. 이러한 점 때문에 다대일 양방향 매핑을 고려할 수도 있다. 이는 상황에 따라 더 적합한 것을 사용하는 것이 좋다.
출처: 인프런 김영한님의 자바 ORM 표준 JPA 프로그래밍
https://www.inflearn.com/course/ORM-JPA-Basic
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
회사땜에 매일 바쁜 와중에 학원이라도 다닐까 생각했는데 마침 JPA 강의가 생겨서 꿀 타이밍이네요. 저는 이 전에 JPA 책을 보고 공부 했었는데요 궁금했던 점, 업무에 적용하며 고민하고 해결하
www.inflearn.com
'인프런 - 스프링 > JPA 프로그래밍 - 기본편' 카테고리의 다른 글
[JPA] JPQL 기본 문법과 쿼리 API (0) 2023.12.01 [JPA] 객체지향 쿼리 언어(JPQL) 소개 (0) 2023.12.01 [JPA] 영속성 전이(CASCADE)와 고아 객체 (0) 2023.11.29 [JPA] 즉시 로딩과 지연 로딩 (0) 2023.11.28 [JPA] 프록시 (0) 2023.11.27