묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨
@Transactional을 붙이는 위치가 궁금합니다. (Service, ServiceImpl..)
회원 정보 수정 API를 구현하며 dirty checking을 이용한 회원 정보 update를 사용했습니다.service의 update 메소드를 호출하기 전과 후를 controller단에서 로그를 찍어보니 정보가 잘 변경되는데 DB에는 반영이 되지 않아 애를 먹었습니다.serviceImpl단의 update 메소드에 @Transactional을 붙여서 해결했습니다. 그 전에는 service단의 update 메소드에 @Transactional을 붙였더니 안되더라구요.service단의 메소드에 붙이는 @Transactional와 serviceImpl단의 메소드에 붙이는 @Transactional이 다른 트랜잭션으로 작동하는건지, 그렇다면 어디에 @Transactional을 붙이는게 맞는건지 궁금합니다.
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
무조건적인 @Transactional?
@Service @RequiredArgsConstructor public class SignUpMemberService implements SignUpMemberUseCase { private final MemberRepository memberRepository; @Override public Long invoke(final Command command) { validateEmailIsUnique(command.email()); validateNicknameIsUnique(command.nickname()); validatePhoneIsUnique(command.phone()); final Member member = command.toDomain(); return memberRepository.save(member).getId(); } } @Service @Transactional @RequiredArgsConstructor public class SignUpMemberService implements SignUpMemberUseCase { private final MemberRepository memberRepository; @Override public Long invoke(final Command command) { validateEmailIsUnique(command.email()); validateNicknameIsUnique(command.nickname()); validatePhoneIsUnique(command.phone()); final Member member = command.toDomain(); return memberRepository.save(member).getId(); } }사용자 가입 UseCase에 대한 구현에서 앞단에서는 unique field에 대한 validation을 진행합니다그 후에 memberRepository.save(member)를 진행하는데 (memberRepository는 Data Jpa Repo)아시다시피 SimpleJpaRepository의 save흐름에는 @Transactional이 적용되어 있습니다따라서 이 SignUpMemberService의 invoke 흐름부터 굳이 @Transactional을 걸어야 하는 생각이 듭니다물론 붙임으로써 이 메소드가 writable한 로직을 가진다고 코드레벨에서 알고 JPA를 모르는사람은 SimpleJpaRepository의 구조를 모르기 때문에 가독성?적인 측면에서는 붙이는게 이해에 수월하다고 생각하는데 tx scope를 최대한 짧게 가져가는게 좋다는 생각이 들어서 약간의 고민을 하게 되었습니다
-
미해결재고시스템으로 알아보는 동시성이슈 해결방법
synchronized 와 @Transactional
안녕하세요 재고관리시스템 강의를 복습하며 내용을 정리하는 중 의문이 생겨 질문을 드립니다. 가장 처음에 application code 레벨에서만 동시성을 해결하기 위해 syncrhonized 를 사용할 경우 해당 메서드에는 @Transactional 을 붙여서는 안된다고 설명해 주셨습니다. 실제로 이를 붙일 경우, 동시에 decrease 메서드가 호출되고 해당 로직 내부로 들어가는 것이 가능함을 확인하였습니다. 그런데 여기서 제가 의문이 들었던 것이 있습니다. @Transacitonal 을 사용할 경우 Spring AOP 에 의해 매 번 다른 proxy 인스턴스를 통해 target object 로의 호출을 하게 됩니다. proxy 객체에 대한 lock 은 서로 다른 프록시들 사이에 공유되지 않는다고 하더라도, 내부적으로 호출되는 target 객체에 대한 decrease 메서드는 결국 동일한 객체에 대한 호출을 하기 때문에, 공유되는 lock 에 대한 경쟁이 일어나는 것이 아닌가 생각이 들었습니다. 최종적으로는 target 객체에 대한 synchronized 메서드를 호출하는 것이라면, 단 하나의 스레드만 임계 영역에 들어갈 수 있어야 할 것 같은데, 그렇지 않음을 확인하였습니다. 왜 이런 일이 일어나는 것인지 이해가 잘 되지 않습니다 ㅠㅠ 이와 관련해서 어떤 키워드로 공부해보면 좋을지 추천 가능할까요..?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
@Transactional 내부 메소드 호출
@Slf4j @Service public class MainService { public void methodA() { log.info("=== methodA 시작... ==="); // 비즈니스 로직 A .... methodB(); log.info("=== methodA 종료... ==="); } @Transactional public void methodB() { log.info("=== methodB 시작... ==="); log.info("-> is methodB transaction active? = {}", TransactionSynchronizationManager.isActualTransactionActive()); // 비즈니스 로직 B .... log.info("=== methodB 종료... ==="); } } @Controller @RequiredArgsConstructor public class MainController { private final MainService mainService; public ResponseEntity<Void> transactionalTestMethod() { mainService.methodA(); return ResponseEntity.ok().build(); } }이러한 MainService 구조에서 MainController에서 mainSerivce.methodA()를 호출하게 되면 methodA는 현재 트랜잭션을 유도하지 않고 있고 그 내부적으로 methodB는 내부 프록시 호출이기 때문에 당연히 methodB에는 트랜잭션 처리가 되지 않음은 이해하였습니다 그런데 이와 관련해서 실험을 하던 도중에@Slf4j @Service public class MainService { @Transactional public void methodA() { log.info("=== methodA 시작... ==="); // 비즈니스 로직 A .... methodB(); log.info("=== methodA 종료... ==="); } @Transactional public void methodB() { log.info("=== methodB 시작... ==="); log.info("-> is methodB transaction active? = {}", TransactionSynchronizationManager.isActualTransactionActive()); // 비즈니스 로직 B .... log.info("=== methodB 종료... ==="); } }이러한 MainService 구조에서 mainService.methodA를 호출할 때 methodA에는 트랜잭션 처리가 됨이 당연한데 그 내부적으로 this.methodB를 호출하면 methodB에도 TransactionSynchronizationManager.isActualTransactionActive()의 결과가 true로 나옴에 따라 트랜잭션 처리가 되는 것 같습니다 제가 알고있던 것은 methodA에서 트랜잭션 처리가 진행이 되더라도 methodB는 내부적으로 호출되는 메소드이기 때문에 트랜잭션 처리가 이루어지지 않는다고 알고있었습니다 물론 Log를 찍어도 methodB 전 후에는 Participating transaction 관련 로그는 없었습니다 하지만 methodB에서 TransactionSynchronizationManager.isActualTransactionActive()의 결과가 true로 나옴에 따라 트랜잭션 처리가 유지되는 것 같은데 혹시 위와 같은 구조에서도 트랜잭션 처리가 유효한건가요?
-
미해결재고시스템으로 알아보는 동시성이슈 해결방법
네임드락 코드 관련 질문
NamedLockStockFacade 클래스 decrease() 메서드에 @Transactional 이 안들어가도 되나요?@Transactional이 빠진 코드면 getLock()과 releaseLock()이 사용하는 커넥션이 달라지는 걸로 알고 있습니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
DB connection을 이용한다면 @Transactional 필수일까 ?!!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)예 [질문 내용] 강의 중간에 이런 말을 하셨습니다. @Transactional -> readOnly 옵션을 true 로 초기화하게 되면 성능 최적화도 가능하다. 그런데 개인적으로 강의를 들으면서 이런 "있으면 손해 볼 것 없는 옵션" 들은 꼭 포함되어야 한다고 생각을 합니다. 그런데 굳이 이렇게 선언해서 사용하게 만든 이유를 알 수 있을까요 ?? 저는 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 강의를 수강하지 않았습니다. 때문에 위의 답을 해당 강의에서 찾을 수 있다면 그렇다면 답변 부탁드립니다. 감사합니다.
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@Scheduled 사용 시 @Transactional 메소드 사용 실패 관련
안녕하세요, 강의 잘 듣고 있습니다!! JPA 사용 중에 강의만으로는 어려운 문제를 만나 문의드립니다! JPA 트랜잭션에 대한 오류인것 같고 꽤 오래 찾아았으나, 아직 답을 찾지 못했습니다. 현상은 @Scheduled 가 추가된 메소드에서 다른 서비스 A의 @Transactional 메소드를 호출 시 아래와 같은 에러가 발생합니다. 예시) @Transactional public void changeStatus(Long id, String status) { Obj o = objRepository.findById(id).get(); o.setStatus(status); } 환경 SpringBoot 2.4 이며, 자동으로 설정되는 JpaTransactionManager 를 사용합니다. ============== 에러 메시지 ============== 2021-08-30 18:14:17.536 ERROR 18252 --- [ scheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler.handleError:95 - Unexpected error occurred in scheduled task org.springframework.orm.jpa.JpaSystemException: Unable to perform beforeTransactionCompletion callback: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.; nested exception is org.hibernate.HibernateException: Unable to perform beforeTransactionCompletion callback: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:331) Trace 로그로 볼 때에는 transaction marked for rollback only 라는 메시지도 나옵니다. 변경 감지로 할 경우와, save 메소드를 호출하는 경우 모두 발생하구요.. 제가 무언가 놓치고 있는 게 있다면, 조언 부탁드립니다!!
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
@Transactional 의 rollback 관련 질문입니다
테스트 시 @Transactional 은 기본적으로 rollback 으로 작동한다고 하셨는데 일반적으로 db에서의 rollback 은 db에 쿼리가 나간 이후에 그 결과를 다시 원복하는 것으로 알 고 있습니다. 그런데 이 경우에는 아예 db로 insert 쿼리 자체가 나가지 않은 것으로 보이는데 그러면 최초 영속성 컨텍스트에만 저장하고, 종료 시점에는 db에 쿼리가 나가지 않고 끝나는게 맞나요?