인프런 커뮤니티 질문&답변
사용자 정의 리포지토리에서 변경이 일어나는 경우 @Transactional을 붙여줘야 하나요?
작성
·
968
퀴즈
스프링 데이터 JPA 사용 시 순수 JPA와 비교하여 개발 생산성 측면에서 얻는 주요 이점은 무엇일까요?
모든 쿼리를 수동으로 복잡하게 작성해야 한다
기본 CRUD(저장, 조회 등) 메서드를 인터페이스만으로 자동으로 제공받는다
모든 동적 쿼리 구현이 항상 완전히 자동화된다
데이터베이스 연결 설정을 직접 XML 파일로 관리해야 한다
답변 5
2
안녕하세요. 탁형님
JPA의 모든 데이터 변경은 트랜잭션 안에서 일어나야 합니다. 따라서 트랜잭션을 붙여주는 것이 맞습니다.
(그런데 리포지토리 계층 보다는 서비스 계층에 붙여주는게 더 나은 선택이겠지요?)
참고로 스프링 데이터 JPA의 기본 구현체는 SimpleJpaRepository는 모든 데이터 변경에 @Transactional을 제공합니다. save() 같은 곳에 적용이 되어 있습니다.
감사합니다.
0
탁형님 혹시 서비스 계층에 javax.transaction.Tansactional이 import 되어있는지 양쪽에 확인해주세요^^
만약 서비스 계층에 org.springframework.transaction.annotation.Transactional이 잡혀있는데, 문제가 발생하는 것이면
전체 프로젝트를 압축해서 올려주세요.
감사합니다.
0
에러 메세지는 다음과 같습니다.
Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
jpql로 변경을 처리한 경우에는 말씀하신 것처럼 repository 계층에서 따로 @Transactional을 붙여주지 않아도 잘 동작합니다.
native query를 이용한 부분에서만 위 에러가 발생하고 있습니다.
0
스프링의 트랜잭션은 기본적으로 전파되기 때문에 문제없이 동작해야 하는 것이 맞습니다.
그래서 저도 정확한 이유를 모르겠습니다.
혹시 오류 메시지를 찾으면 말씀해주세요.
0
빠른 답변 감사드립니다.
분명히 서비스 계층에서 붙여줬었는데도 불구하고 에러가 발생해서 Custom Repository 메소드에도 추가로 @Transactional을 붙여줬었습니다.
- 서비스 계층 코드
@Transactional
public void saveCallMessages(String senderIp, String cid, List<STTMessage> messages) {
...
callMessageRepository.bulkInsert(callMessages);
}
- Repository 계층 코드
@Override
@Transactional
public int bulkInsert(List<CallMessage> messages) {
StringBuilder sb = new StringBuilder("insert into call_messages ( ... ) values ");
...
em.createNativeQuery(sb.toString()).executeUpdate();
return messages.size();
}
에러 메세지를 복사해 놓았어야 했는데 죄송합니다ㅜㅜ





