참고 : 스프링 3.x 트랜잭션
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional.
질문
//////////////////////////////
//예제소스
//////////////////////////////
@Service("testService")
public class TestServiceImpl extends AbstractServiceImpl implements TestService
{
@Resource(name = "testDao")
private TestDao testDao;
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void txTest()
{
HashMap<String, String> data01 = new HashMap<String, String>();
data01.put("ID", "0000001");
data01.put("NAME", "스파이더맨");
testDao.createTest01(data01);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void txTest1()
{
HashMap<String, String> data02 = new HashMap<String, String>();
data02.put("ID", "0000002");
data02.put("NAME", "배트맨");
testDao.createTest01(data02);
HashMap<String, String> data01 = new HashMap<String, String>();
data01.put("ID", "0000001");
data01.put("NAME", "스파이더맨");
testDao.createTest01(data01);
}
@Transactional
@Override
public void txTest2()
{
txTest();
txTest1();
}
}
# 현재 상황
ID 는 등록하고자 하는 테이블의 KEY 로 중복 등록 하면 예외가 발생 합니다.
Controller 에서 txTest 와 txTest1 을 따로 호출 하면 스파이더맨만 등록이 되고 배트맨은 등록이 안되는 원하는 결과를 얻을 수 있습니다.
Controller 에서 txTest2를 호출 하면 모두 등록이 안되고 있습니다. (호출한 두 메소드 전체에 걸쳐 트랜잭션 적용됨)
txTest2 에서 @Transactional 을 제거 하고 호출 하면 스파이더맨과 배트맨이 모두 등록이 됩니다. (트랜잭션 적용 안됨)
txTest2 의 @Transactional 을 @Transactional(propagation = Propagation.REQUIRES_NEW) 로 변경해 보았는데 호출한 두 메소드 전체에 걸쳐 트랜잭션이 적용 됩니다.
# 질문
Controller 에서 txTest2 메소드를 호출 하여
txTest() 에서 등록 된 값은 commit 이 되고
txTest1() 에서 등록 된 값은 rollback 이 되게 하고 싶습니다.
(스파이더맨만 등록이 되고 배트맨은 등록이 안되는 원하는 결과)
방법이 없나요?
답변
안녕하세요. 표준프레임워크센터입니다.
Transactional은 Proxy기반으로 동작하기 때문에 직접호출(자기 호출)은 Transaction이 적용되지 않습니다.
즉, txTest2메소드에서 txTest, txTest1을 직접 호출하는 방식으로는 두 메소드의 Transaction이 먹지 않습니다.
처음에 하셨던것처럼 Controller를 통해 txTest, txTest1을 호출하시거나
txTest, txTest1 메소드를 외부 클래스로 빼서(인터페이스 기반이어야합니다) txTest2에서 호출하는 방식으로
Transaction을 적용하시기 바랍니다.
감사합니다.
이걸 몰라서 한참 헤메었다.