728x90
문제
프로젝트를 진행하며 엔티티 수정 로직을 구현하던 도중 다음과 같은 에러가 발생했다.
jakarta.persistence.TransactionRequiredException: Executing an update/delete query
에러가 발생한 로직
Service
public RecommendModifyResponse modifyPost(String userEmail, Long recommendNo, RecommendModifyRequest request) {
// 글을 작성하는 Member 확인
Member member = validateGetMemberInfoByUserEmail(userEmail);
// 수정 글 확인
Recommend recommend = validateGetRecommendInfoByRecommendNo(recommendNo);
// Member와 Recommen의 작성자가 동일한지 확인
if (!Objects.equals(member.getMemberNo(), recommend.getMember().getMemberNo())) {
throw new ContentILikeAppException(ErrorCode.NOT_FOUND, ErrorCode.NOT_FOUND.getMessage());
}
// 수정 게시물
recommendRepository.update(request.getRecommendTitle(), request.getRecommendContent(), request.getRecommendImageUrl(), request.getRecommendYoutubeUrl(), recommendNo);
recommend = validateGetRecommendInfoByRecommendNo(recommendNo);
return new RecommendModifyResponse(recommend.getRecommendNo(), recommend.getRecommendTitle());
}
Repository
public interface RecommendRepository extends JpaRepository<Recommend, Long> {
...
@Modifying(clearAutomatically = true)
@Query("update Recommend r set r.recommendTitle = :title, r.recommendContent = :content, r.recommendImageUrl = :image, r.recommendYoutubeUrl = :youtube ,r.lastModifiedAt = current_timestamp where r.recommendNo = :recommendNo ")
void update(@Param("title") String recommendTitle, @Param("content") String recommendContent, @Param("image") String recommendImageUrl, @Param("youtube") String recommendYoutubeUrl, @Param("recommendNo") Long recommendNo);
}
해결법
update나 delete 쿼리를 사용할 때에는 @Transaction 처리가 필요하다.
Service나 Repository 중 한 곳에서 @Transaction 어노테이션을 붙이면 해당 예외는 해결된다.
@Transactional
public RecommendModifyResponse modifyPost(String userEmail, Long recommendNo, RecommendModifyRequest request) {
// 글을 작성하는 Member 확인
Member member = validateGetMemberInfoByUserEmail(userEmail);
// 수정 글 확인
Recommend recommend = validateGetRecommendInfoByRecommendNo(recommendNo);
// Member와 Recommen의 작성자가 동일한지 확인
if (!Objects.equals(member.getMemberNo(), recommend.getMember().getMemberNo())) {
throw new ContentILikeAppException(ErrorCode.NOT_FOUND, ErrorCode.NOT_FOUND.getMessage());
}
// 수정 게시물
recommendRepository.update(request.getRecommendTitle(), request.getRecommendContent(), request.getRecommendImageUrl(), request.getRecommendYoutubeUrl(), recommendNo);
recommend = validateGetRecommendInfoByRecommendNo(recommendNo);
return new RecommendModifyResponse(recommend.getRecommendNo(), recommend.getRecommendTitle());
}
이유
JpaRepository를 상속받아 메서드를 사용하게 되면 상위에 있는 SimpleJpaRepository의 delete, save를 사용하게 되는데
해당 코드들에는 @Transaction 어노테이션이 이미 작성되어 있기 때문에 따로 트랜잭션 처리를 하지 않아도 된다.
하지만 내 코드를 보게 되면 @Query를 사용하여 직접 쿼리를 작성하여 JpaRepository를 통해 명령을 실행시키는 것이 아니기 때문에 트랜잭션 추가가 필요한 것이다.
참조
반응형