작성
·
633
0
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)
[질문 내용]
아래는 제가 강의를 듣고 직접 변형 코드를 작성하면서 정리한 내용입니다.
강의 중 member - team의 관계가 comment - team 으로 변경 되었다고 생각하시면 되겠습니다.
제일 아래에 제 질문이 있습니다.
요약하자면, findByXXX 등으로 다대일 단방향 관계에서도 원활하게 데이터를 가져올 수 있는 것 같은데, 굳이 양방향을 사용하는 이유는 객체 지향적으로 코드를 짜기 위함인지, SQL 등에서 이점이 있는 지에 대해 궁금합니다.
댓글 같은 경우는 commentRepository에서 findByWriter로 가져오는 게 효율적인가? 아니면 Post 엔티티에서 comments에 대한 List 연관관계를 설정하고 가져오는 게 효율적인가?
편한 건 post.getComments 로 가져오나, commentsService.findByWriter(Post post) 를 호출시켜서 가져오나 비슷한 것 같다.
그런데 전자로 할 땐 account와 post 에만 select 문이 나가고, 후자로 할 땐 comments에 대한 select 문이 추가로 나간다.
좋아요같은 경우는 자주 조회되니 post.getComments를 해두는 게 좋은건가?
public void setPost(Post post) {
this.post = post;
post.getComments().add(this);
}
어차피 em.persist(comment)에서 외래 키 값을 comment의 post에서 꺼내서 넣으면서 DB에 반영이 되며, JPA에서 실제 Post의 데이터를 사용하는 시점에 쿼리를 날린다. (지연로딩) 그래서 값을 세팅해주지 않아도 값이 출력이 된다.
그러나 객체지향적으로 생각해보면 양쪽 다 값을 입력하는 것이 맞다.
또한 post.getComments().add(this); 를 넣어주지 않으면 2군데서 문제가 생긴다.
em.flush와 em.clear를 하지 않는 상황
flush와 clear를 하면 1차 캐시에 아무것도 없으므로 DB에서 다시 조회해온다. 그래서 JPA가 FK가 있다는 것도 알고, 매커니즘이 동작한다.
em.find해서 post을 가져올 때, 해당 post은 영속 컨텍스트의 1차 캐시에 있다. 위에 코드에서 세팅된 값 그대로 메모리에 올라가 있다.
comments 컬렉션에 값이 있을까? 없다. 순수한 객체 상태이다.
테스트 케이스 작성
테스트 케이스를 작성할 때는 JPA 없이도 동작하도록 순수한 자바 단위로 테스트를 작성한다. 이때, 에러가 발생한다.
순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하자.
JPA에서의 설계는, 단방향 매핑만으로도 이미 연관관계 매핑은 완료
테이블과 객체를 매핑한다는 관점에서만 보면, 단방향만으로도 설계가 완료된다.
양방향 매핑은 반대방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐
객체 입장에서는 양방향으로 설계해서 좋을 게 없다. 연관관계 편의 메서드 등 고민거리만 많아진다.
그러나 실무에선, JPQL에서 역방향으로 탐색할 일이 많다. 그때 양방향으로 하면 된다.
단방향 매핑을 잘하고 양방향은 필요할 때 추가해도 됨. (테이블에 영향을 주지 않음. 그냥 반대방향에서 컬렉션만 추가된 것.)
즉, 설계할 때는 단방향 매핑만으로만 설계하고, 개발에 들어가서 양방향을 고민해도 늦지 않다. 객체 입장에서는 양방향 매핑에 대한 이득이 없다. 필요하다면 연관관계 편의 메서드로 양방향을 설정해주자.
JPQL에서 역방향으로 탐색할 일이 많을 때 양방향으로 설정해야 하는 이유는 뭐지?
코드를 객체지향적으로 짜기 위함인가, 아니면 SQL 쿼리에서 이점을 얻을 수 있는 건가?
만약 둘 중 하나를 선택한다면, 나머지 하나는 없어도 되는 건가?
양방향 연관관계 설정하고 post.comments로 JpaRepository의 findByWriter 역할을 대체한다면, findByWriter는 없어도 되는건가?
영속 컨텍스트 1차 캐시에 없는 상태에서 post.getComments()로 가져올 때, Comment 에 대한 SQL에 select 문이 나가지 않는 이유는? 영속 컨텍스트 1차 캐시에 없는 상태에서 post.getComments()로 가져올 때, Comment 에 대한 SQL에 select 문이 나가지 않는 이유는?
// Comment Select문 실행됨.
@Transactional(readOnly = true)
public List<Comment> findByPost(Long postId) {
Post post = postService.findById(postId);
return commentRepository.findByPost(post);
}
// 연관관계 편의 메소드를 사용한 코드
// Comment Select문 실행되지 않음. 값은 정상적으로 출력됨.
@Transactional(readOnly = true)
public List<Comment> findByPostObj(Long postId) {
Post post = postService.findById(postId);
List<Comment> commentList = post.getCommentList();
log.info("post.getCommentList = {}", commentList);
return commentList;
}
답변 1
1
안녕하세요. Beomjin Kim님, 공식 서포터즈 David입니다.
JPA(ORM)를 사용하는 이유 중 하나는 객체지향적으로 코드를 작성하기 위해서 입니다.
양방향과 관련된 내용은 다음 글 답변을 참고해주세요.
https://www.inflearn.com/questions/268269
쿼리의 경우 post를 가져오는 쿼리를 봐야 자세히 답변 드릴 수 있습니다.
추측으로는 comment를 join해서 들고 오는 건 아닐까 싶네요.
감사합니다.