JPQL의 2가지 문제?

midas·2022년 5월 23일
0

JPQL 영속성 동기화 문제

public interface PostRepository extends JpaRepository<Post, Long> {

	@Modifying
	@Query("update Post p set p.likeCount = p.likeCount + :count where p.id = :id")
	int updateLikeCount(@Param("count") long count, @Param("id") Long id);
}

@Slf4j
@SpringBootTest
class PostRepositoryTest {

	@Autowired
	private PostRepository postRepository;

	Post post = new Post("test-title", 5);

	@Test
	@Transactional
	void 영속성_테스트() {
	  // given
		postRepository.save(post);
		log.info("before: post -> {}", post);

		// when
		postRepository.updateLikeCount(10, post.getId());

	  // then
		Optional<Post> foundPost = postRepository.findById(post.getId());
		assertThat(foundPost.isEmpty(), is(false));

		log.info("after: post -> {}", post);
		assertThat(foundPost.get().getLikeCount(), is(15L)); //🤔 바로 이곳의 결과는!?
	}
}

😳 이 머선 129!?
분명히 Update를 했고 쿼리도 제대로 나갔는데, 결과는 왜 이럴까요?
하지만! JPQL을 사용하는 경우에는 JPA Entity LifeCycle을 무시(영속성 무시)하고 쿼리가 실행됩니다.
여기서 DB와 영속성 컨텍스트의 동기화가 깨지게 됩니다.

DB로 바로 쿼리를 날리고 끝이 났으니.. 영속성은 변경이 안된 그대로인데
조회를 했을 때, 영속성 컨텍스트에 변경 안된 값을 가져오는 것입니다.

이러한 문제를 피하기 위해서는 어떤 방법을 써야 될까요?
이것을 위한 @Modifying에는 clearAutomatically 속성이 있습니다.

@Modifying(clearAutomatically = true)
@Query("update Post p set p.likeCount = p.likeCount + :count where p.id = :id")
int updateLikeCount(@Param("count") long count, @Param("id") Long id);

위와 같이 clearAutomatically 속성을 주고 다시 실행시켜 주면?

Update 이후 영속성 컨텍스트가 깔끔하게 비워지기 때문에, 다시 조회 쿼리가 날아가는 것을 볼 수 있습니다.
그리고 테스트 결과도 OK!

트랜잭션 문제

참고

profile
BackEnd 개발 일기

0개의 댓글