Database/JPA

@ EnableTransactionManagement Advice Mode PROXY와 ASPECTJ

BUST 2018. 6. 3. 16:40

낙관적 Lock (Optimistic Lock)을 이용해서 비즈니스 로직을 처리를 할때 클래스의 내부의 함수는  트랙잭션이 제대로 걸리지 않아 데이터가 저장이 되지 않았었다. 이와 관련해서 stackoverflow에 검색을 해보니 관련되서 질문을 올린 사람이 있었다. 관련해서는 실수를 하기 쉬운 것이라고 생각이 되서 블로그 글을 따로 정리를 한다.

Option A

@Transactional
public void generate(){
    // selects
    save(a);
    // more selects
}

@Transactional
public void save(Object a){
    //save the object
}

Option B

public void generate(){
    // selects
    save(a);
    // more selects
}

@Transactional
public void save(Object a){
    //save the object
}

- 위와 같은 같은 클래스의 내에 @Transactional 을 이용하여 트랙잭션을 처리하는 비즈니스 로직 클래스가 있다고 하면 Option A인 경우에는 Save가 작동이 되지만 Option B 인경우에는 작동이 되지 않는다.

- 원인을 찾아보니 @EnableTransactionManagement를 이용하여 트랙젹션 매너지를 enable 시키는데 트랙젹션을 AOP를 이용하여 작동을 시키는 구조이다.

- 여기서 찾아보니 AdviceMode의 기본값의 PROXY이다.

- 즉. @Transcational 이 달린 클래스가 DI 될때의 객체는 한번 감싼 객체인 PROXY 객체가 생성되서 주입이 된다. 

- 그래서 클래스 내부에서의 Method 호출은 직접 적인 PROXY 객체의 호출이 아니기 때문에 호출이 되지 않는다.



private MyClass self; // this is the proxy bean of this class!

public void generate(){
    // selects
    self.save(a);
    // more selects
}

@Transactional
public void save(Object a){
    //save the object
}

- 위와 같은 방법으로 하면 트랙잭션이 작동이 된다.



ASPECTJ 모드를 이용하는 방법

- @EnableTransactionManagement을 선언을 할때 AdviceMode를 설정을 할수 있다. ASPECTJ 모드를 사용한다면 위와 같은 상황에서는 문제가 되지 않는다.
- PROXY 방법과는 달리 직접 바이트 코드를 주입하는 형식이기 때문에 자신의 클래스의 내부 메서드를 호출을 해도 트랙잭션이 코드가 포함된 매서드르르 호출이 된다.

Reference

- https://stackoverflow.com/questions/35601705/transactional-method-inside-method
- https://ko.wikipedia.org/wiki/AspectJ
- https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html


'Database > JPA' 카테고리의 다른 글

JPA 영속성 컨텍스트  (0) 2018.09.08
JPA CascadeType  (0) 2018.09.08
Transactional with jpa repository  (0) 2018.05.28
Database Transaction Lock With JPA  (0) 2018.05.28