@ManyToOne 과 Eager/Lazy Loading
@ManyToOne을 사용시 FK쪽의 엔티티를 가져올때 PK쪽의 엔티티도 같이 가져온다.
실제로 쿼리를 실행하면, 내부적으로 left outer join처리가 되어 데이터를 가져온다.
하지만 매번 이렇게 여러 테이블을 조인하여 가져온다면 효율이 떨어질 것이다.
fetch는 Lazy loading을 권장한다.
위와 같이 연관관계를 가진 모든 엔티티를 같이 로딩하는 것을 'Eager loading'이라고 한다.(즉시 로딩이라고도 한다.)
즉시 로딩은 성능 저하를 피할 수 없는데, JPA에서는 연관관계 데이터를 어떻게 가져올 것인가 를 fetch(패치) 라고 한다.
그리고, 즉시 로딩의 반대 개념을 'Lazy loading'(지연 로딩)이라고 한다.
Board.java의 연관부분을 아래처럼 작성해서 지연로딩을 선언한다.
@ManyToOne(fetch = FetchType.LAZY)
private Member writer;
BoardRepositoryTests
@Test
public void TestRead1(){
Optional<Board> result = boardRepository.findById(100L);
Board board = result.get();
System.out.println(board);
System.out.println(board.getWriter());
}
이대로 테스트를 진행하면? 오류가 난다.
sout(board)는 Board테이블만 가져와서 문제가 발생하지 않지만,
board.getWriter()는 member테이블을 가져와야하지만,FetchType.Lazy를 해줬기 때문에 'no Session'오류가 뜬다.
그래서 @Test위에 @Transactional을 작성해준다.
@Transactional
은 메서드 안에 여러 트랜잭션이 있을경우 이를 하나의 트랜잭션으로 처리하라는 어노테이션이다.
그래서 중간에 session이 끊겨도 필요할때 다시 db와 연결이 된다.
@Transactional
@Test
public void TestRead1(){
//생략
}
결과:
이제는 출력이 잘 되는걸 볼 수 있다.
지연로딩(lazy loading)의 장/단점
조인을 하지 않기 때문에 속도는 빠르지만, 연관관계가 복잡할때는 여러 번의 쿼리가 실행된다는 단점이 있다.
'Spring Boot' 카테고리의 다른 글
[ Spring Boot ] N:1 (다대일) 연관관계 part1 (0) | 2024.08.01 |
---|---|
[ Spring Boot ] 스프링MVC & Thymeleaf part.3 (0) | 2024.07.30 |
[ Spring Boot ] 스프링MVC & Thymeleaf part.2 (0) | 2024.07.30 |
[ Spring Boot ] 스프링MVC & Thymeleaf part.1 (0) | 2024.07.30 |
[ Spring Boot ] @Query 어노테이션, Querydsl (0) | 2024.07.30 |