-
카테고리
-
세부 분야
백엔드
-
해결 여부
해결됨
Collection type으로 Set 대신 List를 사용하는 이유가 있는지요?
21.09.29 15:39 작성 조회수 1.52k
11
1. 강의 내용과 관련된 질문인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)
[질문 내용]
답변을 작성해보세요.
11
김영한
지식공유자2021.09.29
안녕하세요. Catnip님
좋은 질문입니다. Set이 개념적으로 좋지만 실무에서는 성능 이슈가 있습니다.
Set은 중복을 제거해야 하는데, 그렇다는 것은 기존 데이터 중에 중복이 있는지 비교를 해야 합니다. 이게 일반적으로는 크게 문제가 없는데, 지연 로딩으로 컬렉션을 조회했을 때 문제가 됩니다.
컬력션이 아직 초기화 되지 않은 상태에서 컬렉션에 값을 넣게 되면 프록시가 강제로 초기화 되는 문제가 발생합니다. 왜냐하면 중복 데이터가 있는지 비교해야 하는데, 그럴러면 컬렉션에 모든 데이터를 로딩해야 하기 때문입니다.
반면에 List는 이런 중복 체크가 필요없이 때문에 데이터를 추가할 때 초기화가 발생하지 않습니다.
감사합니다.
3
Herb
질문자2021.09.30
말씀해주신 내용을 확인해본 결과로, 혹시 찾아오신 분들께 도움이 될까 싶어 공유합니다.
결론적으로는 말씀해주신대로 (양방향 연관관계 + List)를 취하면 불필요한 fetch가 없을 것 같습니다.
1. 값 타입의 Collection을 변경시킬 경우 말씀대로 Set에서는 데이터가 로딩되고 List에서는 데이터가 로딩되지 않음을 확인하였습니다.
2. 반면 1:N 단방향 연관관계에서는 Collection을 변경시킬 경우 Set, List 모두 데이터가 로딩됨을 확인하였습니다.
(추가)
3. 우리가 N:1 양방향 연관관계의 mappedBy에서도 Set에서만 데이터가 로딩된다는 내용의 Documentation을 찾고 확인하였습니다.
다만 해당 자료는 최근 버전에서 없어지거나 이동한 것으로 보입니다.
옛날 버전(Hibernate 4.3): https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch20.html#performance-collections-mostefficientupdate
최근 버전(Hibernate 5.4): https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#best-practices-mapping-associations
=====
2022/05/29 수정 - Github Gist로 관련 파일만 옮겼습니다.
제가 사용한 코드입니다 (https://gist.github.com/nightlyherb/00447a2ab196dcc3d5cd9e9b01f313ef)
관련 부분
DemoRunner.java
결과
===== Init Lazy Parent =====
Hibernate:
select
parent0_.id as id1_1_0_
from
parent parent0_
where
parent0_.id=?
===== Embeddable Child Set =====
Hibernate:
select
embeddable0_.parent_id as parent_i1_2_0_,
embeddable0_.value as value2_2_0_
from
parent_embeddable_child_list embeddable0_
where
embeddable0_.parent_id=?
===== Embeddable Child List =====
===== Entity Child Set =====
Hibernate:
select
entitychil0_.set_parent_id as set_pare2_0_0_,
entitychil0_.id as id1_0_0_,
entitychil0_.id as id1_0_1_
from
entity_child entitychil0_
where
entitychil0_.set_parent_id=?
===== Entity Child List =====
Hibernate:
select
entitychil0_.list_parent_id as list_par3_0_0_,
entitychil0_.id as id1_0_0_,
entitychil0_.id as id1_0_1_
from
entity_child entitychil0_
where
entitychil0_.list_parent_id=?
===== Bidirectional Mapping Child Set =====
Hibernate:
select
bidirectio0_.set_parent_id as set_pare3_0_0_,
bidirectio0_.id as id1_0_0_,
bidirectio0_.id as id1_0_1_,
bidirectio0_.list_parent_id as list_par2_0_1_,
bidirectio0_.set_parent_id as set_pare3_0_1_
from
bidirectional_mapping_child bidirectio0_
where
bidirectio0_.set_parent_id=?
===== Bidirectional Mapping Child List =====
===== End =====
(그 후 Embeddable Child List의 테이블 전부 날리고 다시 insert하는 쿼리 수행)
1
0
답변 4