본문 바로가기

Spring boot

[spring boot] 3차 정리 (페치 조인, 벌크 연산)

페치 조인 (fetch join)

페치 조인 1 - 기본

fetch LAZY 지연로딩으로 설정해놔도 jpql날릴 때 join fetch 하면 이게 더 우선순위 높아서 팀을 프록시가 아닌 진짜 엔티티로 들고옴. 따라서 그 아래(system.out.println(member.getTeam().getName())도  프록시가 아닌 다 진짜 객체로 사용하는 것. 

 

팀A는 실제 영속성 컨텍스트에 올라간건 1개지만 팀A인 데이터(회원)가 2개이기 때문에 그 1개를 참조하는 값이 2개인것임.

 

원래 distinct는 완전히 같은 데이터만 중복을 제거해주지만 jpa는 일대다 관계에서 뻥튀기되는 데이터까지 중복제거해준다.

 

 

 

 

페치 조인 2 - 한계

fetch join은 나랑 연관된 애들 전부를 끌고오겠다라는 뜻이며 중간에 몇개(예를 들어 id가 1인것만) 골라서 가져오는 것이 아님. 따라서 별칭을 사용할 수 없음. 

 

별칭 사용 안됨의 규칙
만약 팀의 멤버의 5개 중 3개만 select하고 싶다면 걍 첨부터 멤버 5개중 3개를 조회해야함.

 

둘 이상의 컬렉션은 페치 조인 할 수 없다의 규칙

일대다도 뻥튀기 되는데 일대다대다는 엄청 곱하기 됨. 

 

핵심! 일대다(다:컬렉션)을 페치조인하는데 페이징 api사용하고 싶으면 뒤집어서 다대일로 페치조인하여 페이징해라

또는  @BatchSize(100)

데이터 150개면 처음에 100개를 한 쿼리 안에서 보내달라고 요청하고 나머지 50개를 보내달라고 요청 

 

 

 


 

벌크 연산

벌크연산 : 하나만 딱 찝어 update, delete하는거 말고 한번에 여러개를 DB에 바로 update, delete 

영속성 컨텍스트는 이전 데이터 가지고 있지만 DB 속 데이터는 변경되어있음. 다음에 데이터를 조회하면 JPA는 영속성컨텍스트에서 데이터를 가져오기 때문에 변경된 데이터를 가져오지 않음. 따라서 벌크 연산 후에는 영속성 컨텍스트를 날려줘야 함.

 

정리

1. 영속성 컨텍스트에 엔티티가 없는 상태에서 벌크 연산을 먼저 실행한다.

2. 부득이하게(수정쿼리 날리고 바로 조회) 영속성 컨텍스트에 엔티티가 있으면 벌크 연산 직후 영속성 컨텍스트를 초기화 한다.

      벌크 연산 후 em.flush()  = 혹시 DB 에 올라가지 않은 데이터가 남아있을 수도 있기 때문,    

                            +

                       em.clear()  = 영속성 컨텍스트를 비워야 함. (후에 DB속 새로운 데이터가 영속성컨텍스트로 들어오게)

 

 

JPA를 사용한 벌크성 수정 쿼리

// JPA만 사용한 벌크성 수정 쿼리
public int bulkAgePlus(int age) {
 	int resultCount = em.createQuery(
 					"update Member m set m.age = m.age + 1" +
 					"where m.age >= :age")
 			.setParameter("age", age)
 			.executeUpdate();
 	return resultCount;
}
// JPA만 사용한 벌크성 수정 쿼리 테스트
@Test
public void bulkUpdate() throws Exception {
 	//given
 	memberJpaRepository.save(new Member("member1", 10));
 	memberJpaRepository.save(new Member("member2", 19));
 	memberJpaRepository.save(new Member("member3", 20));
 	memberJpaRepository.save(new Member("member4", 21));
 	memberJpaRepository.save(new Member("member5", 40));

	//when
 	int resultCount = memberJpaRepository.bulkAgePlus(20);
 
 	//then
 	assertThat(resultCount).isEqualTo(3);
}

 

스프링 데이터 JPA를 사용한 벌크성 수정 쿼리

핵심

스프링 데이터 jpa 이용하는 방식(interface 상속받아 이름으로 쿼리 날리는 메서드 만들기)에서 @Modifying 추가 + int로 반환받기

참고 : https://baeji-develop.tistory.com/34