해결된 질문
작성
·
2.1K
11
답변 4
11
안녕하세요. Catnip님
좋은 질문입니다. Set이 개념적으로 좋지만 실무에서는 성능 이슈가 있습니다.
Set은 중복을 제거해야 하는데, 그렇다는 것은 기존 데이터 중에 중복이 있는지 비교를 해야 합니다. 이게 일반적으로는 크게 문제가 없는데, 지연 로딩으로 컬렉션을 조회했을 때 문제가 됩니다.
컬력션이 아직 초기화 되지 않은 상태에서 컬렉션에 값을 넣게 되면 프록시가 강제로 초기화 되는 문제가 발생합니다. 왜냐하면 중복 데이터가 있는지 비교해야 하는데, 그럴러면 컬렉션에 모든 데이터를 로딩해야 하기 때문입니다.
반면에 List는 이런 중복 체크가 필요없이 때문에 데이터를 추가할 때 초기화가 발생하지 않습니다.
감사합니다.
안녕하세요. jayjoy05님
일반적으로 데이터베이스에서 데이터를 조회하는 시점부터 데이터를 중복되지 않는 방식으로 조회합니다 🙂
DB에서 이미 중복을 다 제거하고 가져오기 때문에 List를 사용해도 대부분 이슈가 없습니다.
감사합니다.
db에서 중복을 제거하고 가져온다는 말씀이 잘 이해가 가질않는데,
보통 회원의 게시글을 가져올 경우
다대일 양방향매핑관계에서
user.getPostList()이렇게 가져오는거면 단순히 조인해서 가져오는건데 어느 부분에서 중복이 제거된다는 말씀이신지 궁금합니다
안녕하세요. jayjoy05님
user.getPostList()를 호출하는 경우 해당 유저가 작성한 Post들이 조회되는데요.
이 경우에는 특정 사용자가 작성한 Post들만 조회되기 때문에 중복이 발생하지 않습니다.
감사합니다.
3
말씀해주신 내용을 확인해본 결과로, 혹시 찾아오신 분들께 도움이 될까 싶어 공유합니다.
결론적으로는 말씀해주신대로 (양방향 연관관계 + 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
안녕하세요!
그러면 List를 쓰는 것이 성능이 좋다는 말씀이신데,
데이터 중복 방지를 위해 또 다른 로직을 서비스단에 추가를 해야할까요?
아니면 사실상 데이터가 중복돼서 들어올 일이 없기 때문에 성능 이슈가 없는 리스트를 사용하는 것일까요?
예를 들어 좋아요 한 글들을 가져올 때 중복이 없이 가져오는 것이 중요할 것 같은데
리스트는 혹시라도 중복이 있을 수도 있지않을까 해서 여쭤봅니다!