묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
readonly 트랜잭션에 update를 수행하는 분리된 트랜잭션 메서드를 호출 할 때 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)예[질문 내용]안녕하세요 영한님이번에 트랜잭션 적용하면서 @Transactional(readOnly = true) 가 붙은 조회 메서드 내부에 @Transactional(propagation = Propagation.REQUIRES_NEW)가 붙은 외부 클래스의 메서드가 사용 될 때물리 트랜잭션이 분리되었고 각각 다른 트랜잭션임에도변경감지가 적용안되는 부분이 궁금했습니다.아래는 궁금한 부분에 대한 테스트를 진행한 코드입니다. @Service @RequiredArgsConstructor public class TeamService { private final TeamRepository teamRepository; private final TeamExternalService externalService; @Transactional(readOnly = true) public Team findTeamWithNameChangeExternal(Team team, String name) { Team findTeam = teamRepository.findByName(team.getName()); externalService.changeName(findTeam, name); return findTeam; } } @Service @RequiredArgsConstructor public class TeamExternalService { @Transactional(propagation = Propagation.REQUIRES_NEW) public void changeName(Team findTeam, String name) { findTeam.setName(name); } } @Test void findTeamWithNameChangeExternal() { Team team = new Team("team"); Team savedTeam = teamRepository.save(team); teamService.findTeamWithNameChangeExternal(savedTeam, "changeName"); Team findTeam = teamRepository.findByName("changeName"); assertThat(findTeam.getName()).isEqualTo("changeName"); }같은 클래스에서 내부 호출 할 경우에는 REQUIRES_NEW를 적용하더라도 같은 프록시 객체로 해당 메서드가 호출된 상위 트랜잭션의 옵션을 그대로 따라 가기 때문에 변경 감지가 적용안된다고 생각했어요 하지만 이와 다른 외부 클래스의 분리된 트랜잭션에서는 변경 감지가 일어나는 것이 정상이라고 생각했는데왜 변경 감지가 일어나지 않는 것일 까요 ..? 아래는 궁금해서 디버그를 찍어봤어요보니가 두 트랜잭션의 번호가 Transaction@13592로 같고 REQUIRES_NEW가 적용된 트랜잭션의 경우에는 oldTrasactionInfo 이라는 정보를 갖고 해당 메서드를 실행하는 @Transactional(readOnly = true)옵션이 적혀있더라구요 ??그렇다면 내부 호출이 아닌 외부 호출이라도readOnly = true로 조회 성능을 챙기면서 변경 감지를 사용할 순 없는 것인가요 ??
-
미해결스프링 핵심 원리 - 기본편
@Transactional 안에서 외부 서비스 api call 관련 질문있습니다.
@tranactional 이 붙은 메소드 안에서 외부 서비스 api를 call 해야하는 상황이 있는데컨트롤러 단에서 로직 분리가 힘든 상황입니다. @tranactional 이 붙은 메소드 안에서 아래와 같이 TransactionSynchronizationManager를 선언하고 override한 aftercommit 내부에서 호출하게 될 경우마찬가지로 외부 서비스 api에 장애가 발생했을 때도 본 서비스에 장애로 이어질 수 있을까요?? TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { @Override public void afterCommit() { // 여기서 외부서비스 api 호출 } });
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@PostConstruct 지정 함수 @Transactional 지정 시 컨텍스트 관리가 안되는 경우
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 역시 백문이 불여일타!! 강의 보고 혼자 샘플작성하다 막 터집니다. 강의 볼때는 '음~ 그렇지~' 하고 보던게 안보고 혼자 작성해보니 강사님이 말씀하시는 "이거 분명이 개발할 때 문제 발생합니다." 하는거 다 터지네요. [질문 내용] InitDB.java 샘플 따라하다가 궁금한점이 생겨 질문 드립니다. 애플리케이션 구동 시 초기 데이터를 넣기 위해 @PostConstruct 로 코드를 작성하는 부분에서 문제가 발생했습니다. "Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call" 결론은 영속성 관리가 안되는 문제인거 같습니다. 근데 @Transactional을 붙였고 내부 함수 호출도 아닌데 왜 관리가 안되냐해서 디버깅을 해봤습니다. PostConstruct 하는 부분을 따라가 보니 해당 함수를 invoke하는 클래스가 프록시가 아니더군요. InitDB의 내부 맴버는 프록시인데. 질문: PostConstruct를 호출되는 대상 클래스도 spring container에 있는 bean같은데 왜 저넘은 프록시가 아닌거죠? 다른 bean의 맴버로 주입되는 bean만 프록시인 건가요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
서비스 계층에 트랜잭션 추가 하는 이유
서비스 계층에 @Transactional 을 추가하셨는데 이유가 궁금하고 그 역할이 궁금합니다! Test클래스의 메서드 위에 붙인거랑은 어떤차이가 있는건가요??
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
추상클래스와 @transactional 질문입니다.
안녕하세요 영한님 JPA 수업을 정말 잘듣고 있으며 이 수업을 듣고 제가 실무에서 적용을 하면서 인정받고 있어서 정말 감사합니다.실무를 하던 중 문제는 해결하였으나 원리가 잘 이해가 안가는 부분이 있는데 구글리을 해도 좀처럼 나오지 않아 이렇게 질문을 드립니다 문제가 되는 코드는 실무코드라 간추린 버전으로 올리겠습니다. 추상클래스 입니다. method1()은 구현을 했으며 method2()는 추상메소드입니다 구현클래스이고 추상 메소드인 method2만 오버라이딩하여 구현했습니다 이상황에서 ExampleClass ex = new ExampleClass(); ex.method1(); 이렇게 실행했을 때 저는 생각한 것이 - ExampleClass는 상속을 받았으므로 method1()이 있다. - ExampleClass에 @transactional을 걸었으므로 method1()에도 @transactional이 걸릴 것이다 그런데 막상 실행해보니 트랜잭션이 실행되지 않더군요 그래서 여러가지시도를 한 결과 부모클래스인 AbstractExampleClass에 @transactional을 걸으니 해결되었었습니다. 그런데 문제는 해결했으나 원리가 잘 이해가 되지 않습니다. - ex.method1()를 실행하면 ExampleClass에 @transactional이 있으므로 AOP에서 트랜잭션을 실행해주는 것이 아닌가? 이런 생각이 들더군요 아마 제가 @transactional과 AOP의 자세한 구동원리를 잘 몰라서 그런거 같은데 왜 ExampleClass에 @transactional을 붙이면 안되고 추상클래스에 붙여야 하는지 원리를 자세히 알 수 있을까요?