자잘한 에러

Controller에서의 Trasaction과 JPA 변경감지

기발개발 2022. 11. 24. 01:52

 

Spring data jpa를 사용해서 다음과 같이

Controller 단에서 save() 메소드를 실행해봤다.

@RequiredArgsConstructor
@Controller
public class HomeController {
    private final IdeaRepository ideaRepository;
	
    @PostContruct
    @Trasactional
    public void initDummyData(){
      	 Idea idea = new Idea();
         ideaRepository.save(idea);
    }

}

안 된다.

Spring은 @Trasactional은 Controller단에서 적용이 안되게 되어있다.

 

 

그런데 여기서 중요한건 @Trasactional이 Controller에서 적용되지 않는 점이 아니다.

왜 적용이 안될까?    가 중요하다.

 

Spring AOP는 기본적으로 다이내믹 프록시 기법을 시용해 동작하는데

다이내믹 프록시를 적용하려면 인터페이스가 필요하다.

일반적으로 Controller 클래스는 인터페이스의 구현체가 아니기 때문에

@Transactional 어노테이션이 적용이 되지 않았던 것이다.

 

그럼 인터페이스가 존재하지 않는 클래스에 @Transactional 어노테이션을 적용하려면...

스프링이 지원하는 클래스 프록시 모드를 사용하면된다.

클래스 프록시 모드를 사용하기 위해서는 application context파일에

트랜잭션 관련 설정을 아래와 같이 하면 된다. 

<annotation-driven proxy-target-class="true"/></annotation-driven>

 

 

다만 이렇게 하는 것보다는 원래 spring 의도에 맞게 개발하는것이 맞다. 

Controller 단에 @Transactional 어노테이션이 필요한 경우는

대부분 코드가 지저분하고, MVC 모델에도 맞지 않고,

클래스간의 의존성 및 중복 코딩이 여기저기 널부러져 있는 경우가 대부분이다.

따라서 리팩토링을 통해 Service 클래스에 트랜잭션

이 필요한 비지니스 로직을 작성하고,

Controller 클래스에서는 단순히 HTTP 요청에 맞

비지니스 로직을 호출하는 구조로 변경하자.