AOP 트랜잭션 설정에 대해서..

913 views
Skip to first unread message

미랭군

unread,
Aug 25, 2010, 3:02:13 AM8/25/10
to Korea Spring User Group
아~! 저도 드디어 점심시간에 토스3를 질렀습니다. 내일이면 도착하겠군여^^;;

아래까지 데이타소스 주입하는 것까진 완료가 되었는데 트랜잭션 설정에서

또 다시 막히고 있네요.

infrastructure-config.xml라는 부모 AC에

<tx:annotation-driven transaction-manager="JdbcTransactionManager"/>

라고 태그를 등록을 해놓고

DAO클래스 안에

Insert를 담당하는 메소드 한개를 만들었습니다.

@Transactional(readOnly=true,rollbackFor={SQLException.class})
public List<Object> saveBatch(xxx, xxx){
블라블라
}

이런식으로 해놨는데 readOnly를 true로 설정해놨으면

인서트를 하게 되면 롤백해야 되지 않나요?

그런데 아무 이상없이 데이터가 잘 입력되네요.

또 Web-logic과 같은 경우의 엔터프라이즈 WAS일 경우엔 JTA를 지원하고

글로벌 트랜잭션을 지원한다고 알고 있는데

<tx:jta-transaction-manager/>

이렇게 스프링에 명시적으로 트랜잭션에 관련한 매니져를 등록 안해줬을 경우에는

글로벌 트랜잭션 처리를 어떤 식으로 해주게 되는지 대해서 아시는 분 계신가요?

따로 지정 안해줬을 시엔 디폴트로 하게 되나요?

Sungchul Park

unread,
Aug 25, 2010, 4:00:33 AM8/25/10
to ks...@googlegroups.com

> 이런식으로 해놨는데 readOnly를 true로 설정해놨으면
>
> 인서트를 하게 되면 롤백해야 되지 않나요?
>
> 그런데 아무 이상없이 데이터가 잘 입력되네요.
>
흠... 스프링이 SQLException을 DataAccessException으로 변환하기 때문에
SQLException을 기다리면 안 될거에요. 그런데 잘 들어간다니 뭔가 설정이 잘
못되었나봅니다.
DAO도 부모 AC 안에 있는 거죠?

> <tx:jta-transaction-manager/>
> 이렇게 스프링에 명시적으로 트랜잭션에 관련한 매니져를 등록 안해줬을 경우에는
> 글로벌 트랜잭션 처리를 어떤 식으로 해주게 되는지 대해서 아시는 분 계신가요?
> 따로 지정 안해줬을 시엔 디폴트로 하게 되나요?
질문의 의도를 잘 모르겠습니다. 스프링에 jta transaction manager를 설정하
지 않고도 스프링과 연동시키고 싶다는 뜻인가요? 아니면 스프링과 관계 없이
별도로 사용할 방법이 있냐는 뜻인가요?

일단 지금 사용하시는 DataSource가 XA Datasource인지 확인해야하고... 만약
그렇다면 직접 JNDI lookup으로 Jta transaction manager를 얻어와서 프로그
램에서 트랜젝션 처리를 할 수는 있겠습니다. 하지만 그 datasource를 스프링
에 설정한 jdbc transaction manager에 주입해 놓은 상황이라면 transaction
처리에 충돌이 일어날 것 같은데요.

미랭군

unread,
Aug 25, 2010, 4:21:23 AM8/25/10
to Korea Spring User Group
네 DAO도 부모AC(listener로 읽어들이는)에 정의해놓았습니다.

이런식으로 정의해놓았습니다.

<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(*
base..service.*Service.*(..))" />
</aop:config>

<bean id="JdbcTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="oracleDataSource"/>
</bean>

<tx:annotation-driven transaction-manager="JdbcTransactionManager"/>

<tx:advice id="txAdvice" transaction-
manager="JdbcTransactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>

이런식으로요. 전체적인 트랜잭션 윤곽은 이렇게 xml based aop로 설정해놓고

세부적인 것은 직접 @Transactional 어노테이션을 걸어놨는데요. 테스트를 해볼겸

제가 일부러 insert하는 메소드에 readonly를 걸어봤거든요.

설정이 무언가 잘못된건가요? 아니면 이와 관련된 lib가 부족한건가요;;;?


성철님 말씀대로라면 rollbackFor={SQLException.class})를

DataAccessException.class로 대체하면 롤백처리가 제대로 되겠군요?

Sanghyuk Jung

unread,
Aug 25, 2010, 7:14:00 AM8/25/10
to ks...@googlegroups.com
데이터 입력을 혹시 테스트 코드 안 에서 하셨나요? 트랜잭션이 REQUIRED로 되어 있으면 테스트 코드를 실행시키는 Transaction에 합류하게 되면서 그 전 트랜잭션의 속성을 타게되었는지도 모르겠네요.
 
 그리고 readonly 안에서 insert를 할 때 원래 스프링에서 던지는 Exception은 DataAccessException의 하위 Exception인 TransientDataAccessException인데, 디폴트 설정이 runtime exception일때는 rollback이 되는 것으로 알고 있어서, 따로 Exception지정을 할 필요는 없지 않을까 합니다.
 


 
2010년 8월 25일 오후 5:21, 미랭군 <devz...@gmail.com>님의 말:
--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.


Sanghyuk Jung

unread,
Aug 25, 2010, 7:15:06 AM8/25/10
to ks...@googlegroups.com

"성철님 말씀대로라면 rollbackFor={SQLException.class})를

DataAccessException.class로 대체하면 롤백처리가 제대로 되겠군요? "
 
이 부분도 직접 해보시고 공유해 주시면 다른 분들께도 더욱 도움이 될 것 같네요~ ^^

2010년 8월 25일 오후 8:14, Sanghyuk Jung <ben...@gmail.com>님의 말:

미랭군

unread,
Aug 25, 2010, 8:06:21 AM8/25/10
to Korea Spring User Group
흠..rollbackFor자체를 없앤 후 테스트 해봐도 안되고 DataAccessException.class로 해도 안되네요.

지금 트랜잭션 자체가 안 먹히는 것 같습니다.

@Transactional로 해도 안 먹고 xml에 포인트컷해서 해도 안 먹고..이상하네요;;

트랜잭션이 적용된 아주 심플한 예제가 어디 없을까요;;어디서부터 잘못된건지..

원격으로 설정 좀 봐주실 분 안계신가요? 다들 바쁘시려나;;

On 8월25일, 오후8시15분, Sanghyuk Jung <bene...@gmail.com> wrote:
> "성철님 말씀대로라면 rollbackFor={SQLException.class})를
> DataAccessException.class로 대체하면 롤백처리가 제대로 되겠군요? "
>
> 이 부분도 직접 해보시고 공유해 주시면 다른 분들께도 더욱 도움이 될 것 같네요~ ^^
>

> 2010년 8월 25일 오후 8:14, Sanghyuk Jung <bene...@gmail.com>님의 말:


>
>
>
> > 데이터 입력을 혹시 테스트 코드 안 에서 하셨나요? 트랜잭션이 REQUIRED로 되어 있으면 테스트 코드를 실행시키는
> > Transaction에 합류하게 되면서 그 전 트랜잭션의 속성을 타게되었는지도 모르겠네요.
>
> > 그리고 readonly 안에서 insert를 할 때 원래 스프링에서 던지는 Exception은 DataAccessException의
> > 하위 Exception인 TransientDataAccessException인데, 디폴트 설정이 runtime exception일때는
> > rollback이 되는 것으로 알고 있어서, 따로 Exception지정을 할 필요는 없지 않을까 합니다.
>

> > 2010년 8월 25일 오후 5:21, 미랭군 <devzer...@gmail.com>님의 말:

> >> 그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com<ksug%2Bunsu...@googlegroups.com>로
> >> 이메일을 보내주세요.
> >> 더 많은 옵션을 보려면http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.- 원본 텍스트 숨기기 -
>
> - 원본 텍스트 보기 -

Sungchul Park

unread,
Aug 25, 2010, 10:41:18 AM8/25/10
to ks...@googlegroups.com
AOP로 트랜젝션 설정한 부분은 잠시 막아두고 빼고 <tx:annotation-driven
... /> 만 살려두면 어떤가요?

미랭군

unread,
Aug 25, 2010, 11:28:16 AM8/25/10
to Korea Spring User Group
성철님께서 말씀하신대로 다 지운 상태에서

<bean id="JdbcTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="oracleDataSource"/>
</bean>
<tx:annotation-driven transaction-manager="JdbcTransactionManager"/>

이렇게만 적용한 상태에서..

DAO에 이렇게 어노테이션을 걸어놓고..

@Transactional(readOnly=true)
public void saveCode(UserVo vo) {
블라블라
}

실행을 시켜봤는데도 에러 없이 입력이 잘되네여;;

> >> - 원본 텍스트 보기 -- 원본 텍스트 숨기기 -

One Bread

unread,
Aug 25, 2010, 4:25:46 PM8/25/10
to ks...@googlegroups.com
saveCode()가 처음으로 트랜잭션이 걸리는 메소드인가요? 그러니까 @Transactional이 붙은 메소드 중에서 컨트롤러 등에서 최초로 호출되는 코드인가 하는 질문이에요.

2010/8/26 미랭군 <devz...@gmail.com>

Kuwon Kang

unread,
Aug 25, 2010, 8:20:23 PM8/25/10
to ks...@googlegroups.com
두가지를 먼저 점검해보면 좋을 것 같습니다.

1. pointcut expression이 정확히 해당 DAO의 패키지 구조와 일치하는지?
    execution(* base..service.*
Service.*(..))" 
 
   위의 구조대로라면 ???Service 클래스가가 base아래 하위 패키지가 있을 수 있고 service패키지 바로 아래 존재해야만 하는 건데요.
   이 부분을 확인해 보시면 좋을 것 같습니다.

2. 실제 해당 DAO가 걸리는지.
    saveCode메서드에 디버그 break point를 걸어 두시고 Eclipse Debug화면에서 Stack Trace를 보시면 TransactionInterceptor로 부터 호출이 되는지를 확인해 보시면 좋을 것 같습니다.

Thread [main] (Suspended (breakpoint at line 9 in AOPServiceImpl))
AOPServiceImpl.getWorld() line: 9
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 310
ReflectiveMethodInvocation.invokeJoinpoint() line: 182
ReflectiveMethodInvocation.proceed() line: 149
TransactionInterceptor.invoke(MethodInvocation) line: 106
ReflectiveMethodInvocation.proceed() line: 171
ExposeInvocationInterceptor.invoke(MethodInvocation) line: 89
ReflectiveMethodInvocation.proceed() line: 171
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 204
$Proxy9.getWorld() line: not available
AOPServiceImplTests.getWorld() line: 23
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
SpringTestMethod.invoke(Object) line: 163
SpringMethodRoadie.runTestMethod() line: 233
SpringMethodRoadie$RunBeforesThenTestThenAfters.run() line: 333
SpringMethodRoadie.runWithRepetitions(Runnable) line: 217
SpringMethodRoadie.runTest() line: 197
SpringMethodRoadie.run() line: 143
SpringJUnit4ClassRunner.invokeTestMethod(Method, RunNotifier) line: 142
SpringJUnit4ClassRunner(JUnit4ClassRunner).runMethods(RunNotifier) line: 51
JUnit4ClassRunner$1.run() line: 44
ClassRoadie.runUnprotected() line: 27
ClassRoadie.runProtected() line: 37
SpringJUnit4ClassRunner(JUnit4ClassRunner).run(RunNotifier) line: 42
JUnit4TestMethodReference(JUnit4TestReference).run(TestExecution) line: 38
TestExecution.run(ITestReference[]) line: 38
RemoteTestRunner.runTests(String[], String, TestExecution) line: 460
RemoteTestRunner.runTests(TestExecution) line: 673
RemoteTestRunner.run() line: 386
RemoteTestRunner.main(String[]) line: 196


2010/8/25 미랭군 <devz...@gmail.com>
--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--
Blessings.
Kuwon Kang
............................................................
IT specialist and architect.
Java technology engineer.
JavaEE architect/developer.
Spring Framework specialist.
Solution developer.

- Model Driven Architecture.
- Test Driven Development.
- Test Driven Software Design.
- Refactoring Oriented Development.
- Practical design and modeling.
- Robust  Software Design and Engineering.
............................................................
Prever,Inc.
 http://www.prever.co.kr/
Blog:
 http://josh.prever.co.kr/
............................................................

God's love is eternal and leads us to live for heaven and His glory

Kuwon Kang

unread,
Aug 25, 2010, 8:26:56 PM8/25/10
to ks...@googlegroups.com
추가 질문이 있는데요?

expression에 포함된 Service란 녀석이 DAO인가요?
아니면 Service 따로 DAO따로 각각 스프링 빈으로 등록되어 있나요?
만약 DAO에 메서드에 transactional annotation을 쓰실거면 expression안에 DAO도 포함되어 있어야 겠쬬?

그렇지 않고 Service만 Transactional에 물리려면 그녀석 메서드에 annotation을 설정해야 겠죠?


2010/8/26 Kuwon Kang <preve...@gmail.com>

whites...@gmail.com

unread,
Aug 25, 2010, 8:30:11 PM8/25/10
to ks...@googlegroups.com
혹시 트랜잭션 설정이랑 dao 빈이랑 같은 설정 파일에 등록되어있는지요

Ps: O.B님 질문은 좀 더 복잡한 경우를 추측하신듯 하네요 ㅋ

Ps2: 근데 트랜잭션을 DAO에 거시는군요 보통 서비스에 걸던데 DAO에 거는 이유는 무엇인지 궁금합니다 --토스3 3장 참조

BlackBerry® 에서 보냈습니다.


From: One Bread <onebre...@gmail.com>
Date: Thu, 26 Aug 2010 06:25:46 +1000
Subject: Re: AOP 트랜잭션 설정에 대해서..

미랭군

unread,
Aug 25, 2010, 9:54:21 PM8/25/10
to Korea Spring User Group
드디어 토스3책이 도착했네요^^;; 흑 이메일을 확인해보니

엄청난 리플들을 남겨주셔서 감사할 따름입니다.

빨리 이걸 해결하고 스프링 시큐리티를 적용해야하는데..;;

어쨌든 위에 질문들에 대해서 정리해봤습니다.


> saveCode()가 처음으로 트랜잭션이 걸리는 메소드인가요? 그러니까 @Transactional이 붙은 메소드 중에서 컨트롤러 등에서
> 최초로 호출되는 코드인가 하는 질문이에요.

saveCode()가 최초로 구동되는 메소드입니다.

> pointcut expression이 정확히 해당 DAO의 패키지 구조와 일치하는지? execution(* base..service.*Service.*(..))"

우선 패키지 구조와 AC구조입니다. http://blog.naver.com/zestun/60113818562

base 밑에 두개의 패키지가 있고 그 안에 service 그 안에 CommonService라는 클래스가 있습니다.


> expression에 포함된 Service란 녀석이 DAO인가요?
> 아니면 Service 따로 DAO따로 각각 스프링 빈으로 등록되어 있나요?

CommonService와 CommonDAO 각각 따로 스프링빈으로 등록되어있습니다.

> 혹시 트랜잭션 설정이랑 dao 빈이랑 같은 설정 파일에 등록되어있는지요

네 infrastructure-config.xml안에 등록되어있습니다.

> 근데 트랜잭션을 DAO에 거시는군요 보통 서비스에 걸던데 DAO에 거는 이유는 무엇인지 궁금합니다

별다른 이유는 없습니다. 그냥 기존 프로젝트가 DAO에 걸려있길래 저도 그냥 DAO에 걸어봤습니다 ㅠ

On 8월26일, 오전9시30분, whiteship2...@gmail.com wrote:
> 혹시 트랜잭션 설정이랑 dao 빈이랑 같은 설정 파일에 등록되어있는지요
>
> Ps: O.B님 질문은 좀 더 복잡한 경우를 추측하신듯 하네요 ㅋ
>
> Ps2: 근데 트랜잭션을 DAO에 거시는군요 보통 서비스에 걸던데 DAO에 거는 이유는 무엇인지 궁금합니다 --토스3 3장 참조

> BlackBerry(R) 에서 보냈습니다.


>
>
>
> -----Original Message-----
> From: One Bread <onebread....@gmail.com>
>
> Sender: ks...@googlegroups.com
> Date: Thu, 26 Aug 2010 06:25:46

> To: <ks...@googlegroups.com>
> Reply-To: ks...@googlegroups.com


> Subject: Re: AOP 트랜잭션 설정에 대해서..
>
> saveCode()가 처음으로 트랜잭션이 걸리는 메소드인가요? 그러니까 @Transactional이 붙은 메소드 중에서 컨트롤러 등에서
> 최초로 호출되는 코드인가 하는 질문이에요.
>

> 2010/8/26 미랭군 <devzer...@gmail.com>

> > <ksug%2Bunsu...@googlegroups.com<ksug%252Buns...@googlegroups.com>


> > >로
> > > >>>> 이메일을 보내주세요.
> > > >>>> 더 많은 옵션을 보려면http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.-
> > 원본 텍스트 숨기기 -
> > > >> - 원본 텍스트 보기 -- 원본 텍스트 숨기기 -
>
> > > - 원본 텍스트 보기 -
>
> > --
> > Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
> > 이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
> > 그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com<ksug%2Bunsu...@googlegroups.com>로
> > 이메일을 보내주세요.

> > 더 많은 옵션을 보려면http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.


>
> --
> Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
> 이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
> 그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.

백기선

unread,
Aug 25, 2010, 9:57:03 PM8/25/10
to ks...@googlegroups.com
소스코드를 구글코드나 Git에 올려서 공개해주세요.ㅋㅋ
그게 젤 편하겠어요.

2010년 8월 26일 오전 10:54, 미랭군 <devz...@gmail.com>님의 말:
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--
좋은 하루 되세요~

미랭군

unread,
Aug 25, 2010, 9:59:34 PM8/25/10
to Korea Spring User Group
디버깅 모드로 Daemon Thread밑에 딸린 놈들을

살펴보니 저도 구원님 말씀대로

TransactionInterceptor.invoke(MethodInvocation) line: 106

이렇게 요놈이 딸려있네요.


On 8월26일, 오전10시54분, 미랭군 <devzer...@gmail.com> wrote:
> 드디어 토스3책이 도착했네요^^;; 흑 이메일을 확인해보니
>
> 엄청난 리플들을 남겨주셔서 감사할 따름입니다.
>
> 빨리 이걸 해결하고 스프링 시큐리티를 적용해야하는데..;;
>
> 어쨌든 위에 질문들에 대해서 정리해봤습니다.
>
> > saveCode()가 처음으로 트랜잭션이 걸리는 메소드인가요? 그러니까 @Transactional이 붙은 메소드 중에서 컨트롤러 등에서
> > 최초로 호출되는 코드인가 하는 질문이에요.
>
> saveCode()가 최초로 구동되는 메소드입니다.
>
> > pointcut expression이 정확히 해당 DAO의 패키지 구조와 일치하는지? execution(* base..service.*Service.*(..))"
>

> 우선 패키지 구조와 AC구조입니다.http://blog.naver.com/zestun/60113818562

> ...
>
> 추가 정보 >>- 원본 텍스트 숨기기 -

Kuwon Kang

unread,
Aug 25, 2010, 10:02:15 PM8/25/10
to ks...@googlegroups.com
그러면 해당 interceptor가 바로 Service에 딸린 놈이겠네요.

그럼 DAO메서드에 Annotation을 사용하려면 DAO도 역시 pointcut 대상이 되어야 할 것 같은데요?


2010/8/26 미랭군 <devz...@gmail.com>
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--

미랭군

unread,
Aug 25, 2010, 10:06:38 PM8/25/10
to Korea Spring User Group
<bean id="JdbcTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="oracleDataSource"/>
</bean>
<tx:annotation-driven transaction-manager="JdbcTransactionManager"/>

지금은 성철님 말씀대로 그냥 다 지운 상태에서 이 두개만 남겨놓은 상태입니다.

우선 @Transactional 어노테이션이 먹는지 테스트해보기 위해서요.


On 8월26일, 오전11시02분, Kuwon Kang <prever.k...@gmail.com> wrote:
> 그러면 해당 interceptor가 바로 Service에 딸린 놈이겠네요.
>
> 그럼 DAO메서드에 Annotation을 사용하려면 DAO도 역시 pointcut 대상이 되어야 할 것 같은데요?
>

> 2010/8/26 미랭군 <devzer...@gmail.com>

Kuwon Kang

unread,
Aug 25, 2010, 10:09:39 PM8/25/10
to ks...@googlegroups.com
설명을 하자면 ..

Service에 tx pointcut이 등록이 되면 해당 Service Bean이 호출 될때 해당 메서드의 Annotation을 있는지 검사하고 이 어노테이션이 존재하면
그 속성을 가지고 Transaction을 생성하게 됩니다.

생성후에 실제 메서드를 호출하게 되죠.

그런데 DAO의 메서드에 annotation을 설정하게 되면 TranscationInterceptor가 동작하지 않게 되죠? 이유는 pointcut 대상이 아니기 때문입니다.

따라서 DAO메서드에 선언된 Transactional Annotation은 무의미하게 된거죠.

스프링 트랜젝션이 생각보다 쉬어보이지만 실제 비즈니스 어플의 AOP와 Transaction AOP와 섞어놓고 보면 많이 헷갈리 수 있습니다.

이점을 고려하셔서 Transaction AOP와 Transactional Annotation을 사용하셔야 합니다.



2010/8/26 Kuwon Kang <preve...@gmail.com>

미랭군

unread,
Aug 25, 2010, 11:29:20 PM8/25/10
to Korea Spring User Group
annotation방식으로 트랜잭션을 관리할때도

따로 pointcut을 지정해줘야하나요?

On 8월26일, 오전11시09분, Kuwon Kang <prever.k...@gmail.com> wrote:
> 설명을 하자면 ..
>
> Service에 tx pointcut이 등록이 되면 해당 Service Bean이 호출 될때 해당 메서드의 Annotation을 있는지
> 검사하고 이 어노테이션이 존재하면
> 그 속성을 가지고 Transaction을 생성하게 됩니다.
>
> 생성후에 실제 메서드를 호출하게 되죠.
>
> 그런데 DAO의 메서드에 annotation을 설정하게 되면 TranscationInterceptor가 동작하지 않게 되죠? 이유는
> pointcut 대상이 아니기 때문입니다.
>
> 따라서 DAO메서드에 선언된 Transactional Annotation은 무의미하게 된거죠.
>
> 스프링 트랜젝션이 생각보다 쉬어보이지만 실제 비즈니스 어플의 AOP와 Transaction AOP와 섞어놓고 보면 많이 헷갈리 수
> 있습니다.
>
> 이점을 고려하셔서 Transaction AOP와 Transactional Annotation을 사용하셔야 합니다.
>

> 2010/8/26 Kuwon Kang <prever.k...@gmail.com>


>
>
>
> > 그러면 해당 interceptor가 바로 Service에 딸린 놈이겠네요.
>
> > 그럼 DAO메서드에 Annotation을 사용하려면 DAO도 역시 pointcut 대상이 되어야 할 것 같은데요?
>

> > 2010/8/26 미랭군 <devzer...@gmail.com>

whites...@gmail.com

unread,
Aug 25, 2010, 11:32:09 PM8/25/10
to ks...@googlegroups.com
아니요 그럴필요없답니다
BlackBerry® 에서 보냈습니다.

따로 pointcut을 지정해줘야하나요?

Kuwon Kang

unread,
Aug 26, 2010, 12:21:41 AM8/26/10
to ks...@googlegroups.com
DAO클래스도 transaction pointcut대상으로 한번 지정하고 실행해 보시면 알 수 있지 않을까요?

2010/8/26 미랭군 <devz...@gmail.com>

Kuwon Kang

unread,
Aug 26, 2010, 1:53:51 AM8/26/10
to ks...@googlegroups.com
제가 착각을 했네요.

DAO클래스의 saveCode에 @Transactional을 주었기 때문에 pointcut이 없어도 동작을 하겠군요.


2010/8/26 <whites...@gmail.com>
아니요 그럴필요없답니다

미랭군

unread,
Aug 26, 2010, 2:56:32 AM8/26/10
to Korea Spring User Group
아..혹시나 2.5.6에서 안되는건가 하고 다시 3.0.1로 갈아치우고 해봤는데도 역시나

안되네요..뭐가 문제지;;

GIT나 구글코드를 써본적이 없어서 어떻게 하는지 모르겠습니다ㅠ

기선님 혹시 네이트온 사용하시는지요?

On 8월26일, 오후2시53분, Kuwon Kang <prever.k...@gmail.com> wrote:
> 제가 착각을 했네요.
>
> DAO클래스의 saveCode에 @Transactional을 주었기 때문에 pointcut이 없어도 동작을 하겠군요.
>

> 2010/8/26 <whiteship2...@gmail.com>

whites...@gmail.com

unread,
Aug 26, 2010, 3:00:56 AM8/26/10
to ks...@googlegroups.com
예 지금은 커피숖이라 쫌이따 들어갈께요 ㅋㅋ 한 10분 후...

whites...@lycos.co.kr 추가해주세요
BlackBerry® 에서 보냈습니다.

안되네요..뭐가 문제지;;

기선님 혹시 네이트온 사용하시는지요?

백기선

unread,
Aug 26, 2010, 3:21:53 AM8/26/10
to ks...@googlegroups.com
미랭님 안들어 오시나요? 흠냐.. 대기 중입니다.

2010년 8월 26일 오후 4:00, <whites...@gmail.com>님의 말:



--
좋은 하루 되세요~

미랭군

unread,
Aug 26, 2010, 3:24:13 AM8/26/10
to Korea Spring User Group
whiteship2...@lycos.co.kr로 검색했는데

아이디를 찾을 수 없다고 나옵니다.

구글코드에 프로젝트 올려놨는데

http://reasonframework.googlecode.com/svn

Trunk:Reason_FrameWork

이렇게 만들어놓았습니다

On 8월26일, 오후4시00분, whiteship2...@gmail.com wrote:
> 예 지금은 커피숖이라 쫌이따 들어갈께요 ㅋㅋ 한 10분 후...
>

> whiteship2...@lycos.co.kr 추가해주세요

백기선

unread,
Aug 26, 2010, 3:27:23 AM8/26/10
to ks...@googlegroups.com
엥.. 검색하지 마시고 그냥 추가하시면 될텐데요.


먼가 잘못 적었나; 흠;

코드를 올리셨으니 걍 코드를 볼께요. ㄳㄳ

2010년 8월 26일 오후 4:24, 미랭군 <devz...@gmail.com>님의 말:
--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--
좋은 하루 되세요~

미랭군

unread,
Aug 26, 2010, 3:28:29 AM8/26/10
to Korea Spring User Group
아이디를 찾을 수 없다고 나옵니다..;;

구글코드에 코드 등록해놨습니다.

https://reasonframework.googlecode.com/svn

Trunk명은 Reason_Framework

On 8월26일, 오후4시21분, 백기선 <whiteship2...@gmail.com> wrote:
> 미랭님 안들어 오시나요? 흠냐.. 대기 중입니다.
>

> 2010년 8월 26일 오후 4:00, <whiteship2...@gmail.com>님의 말:


>
>
>
> > 예 지금은 커피숖이라 쫌이따 들어갈께요 ㅋㅋ 한 10분 후...
>

> > whiteship2...@lycos.co.kr 추가해주세요

백기선

unread,
Aug 26, 2010, 3:29:02 AM8/26/10
to ks...@googlegroups.com
넵 받았습니다.

2010년 8월 26일 오후 4:28, 미랭군 <devz...@gmail.com>님의 말:
--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--
좋은 하루 되세요~

Kuwon Kang

unread,
Aug 26, 2010, 3:31:46 AM8/26/10
to ks...@googlegroups.com
저도 미랭군님과 같이 동일한 설정과 환경을 만들어서 여러가지 테스트를 해본결과 Transactional.readonly는 동작하지 않습니다.

readOnly=true를 주어도 insert는 정상 동작 됩니다.

DataSourceUtils와 AbstractTransactionManager를 같이 디버깅 해본결과 Connection.setReadOnly는 정상적으로 호출됩니다.

여러 자료를 이후에 검색해본 결과 JDBC Vendor에 따라 Connection을 구현할 때 readyOnly=true이면 Exception을 내거나 하는 식으로 지원을 하는데 이는 Vendor의 구현에 따라 다르다고 하는군요.

결과 적으로 readOnly는 Vendor에 따라 다르다고 볼 수 있을 것 같습니다.



2010/8/26 Kuwon Kang <preve...@gmail.com>

Sungchul Park

unread,
Aug 26, 2010, 3:34:24 AM8/26/10
to ks...@googlegroups.com

> 여러 자료를 이후에 검색해본 결과 JDBC Vendor에 따라 Connection을 구현
> 할 때 readyOnly=true이면 Exception을 내거나 하는 식으로 지원을 하는데
> 이는 Vendor의 구현에 따라 다르다고 하는군요.
>
> 결과 적으로 readOnly는 Vendor에 따라 다르다고 볼 수 있을 것 같습니다.
>
저도 이 부분이 의심스럽더군요.
JdbcConnection의 readonly 기능이 구현안되었다면 exception이 안 일어나니까요.
그런데 어떤 DB를 사용하신 건가요?

백기선

unread,
Aug 26, 2010, 3:41:18 AM8/26/10
to ks...@googlegroups.com
오라클 쓰고 계시네요

2010년 8월 26일 오후 4:34, Sungchul Park <gyu...@gmail.com>님의 말:

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--
좋은 하루 되세요~

Kuwon Kang

unread,
Aug 26, 2010, 3:46:43 AM8/26/10
to ks...@googlegroups.com
재미있네요.

제가 방금 오라클에 문의 한 결과 Oracle JDBC Driver는 setReadOnly를 지원하지 않는다는 군요.ㅠㅠ

완전 삽질하게 했습니다.ㅠㅠ
그냥 지원 안한다고 JavaDoc에 넣어주면 얼마나 좋을 까...ㅠㅠ

2010/8/26 Sungchul Park <gyu...@gmail.com>

--

Sungchul Park

unread,
Aug 26, 2010, 3:47:57 AM8/26/10
to ks...@googlegroups.com

> 오라클 쓰고 계시네요
>
그렇다면 JDBC 문제가 아니겠네요.
JDBC Driver의 Read only는 잘 작동하는 걸로 아는...

Jdbc 쪽 Log를 찍어보면 어떻게 나오는지 궁금합니다.

Sungchul Park

unread,
Aug 26, 2010, 3:49:07 AM8/26/10
to ks...@googlegroups.com

> 재미있네요.
>
> 제가 방금 오라클에 문의 한 결과 Oracle JDBC Driver는 setReadOnly를 지
> 원하지 않는다는 군요.ㅠㅠ
>
> 완전 삽질하게 했습니다.ㅠㅠ
> 그냥 지원 안한다고 JavaDoc에 넣어주면 얼마나 좋을 까...ㅠㅠ
>
어? 그래요?
전에 저는 그거 썼는데... -_-

그렇다면 문제는 해결된 샘이네요. ;;;

오라클의 Jdbc driver는 대체 언제나 정상 작동하려는 건지...

Kuwon Kang

unread,
Aug 26, 2010, 3:50:22 AM8/26/10
to ks...@googlegroups.com
JDBC또는 RDMBS의 문제일 수 있겠죠. 정확한건 오라클이 어떻게 구현했느냐에 따라 다를 것 같습니다.

하여간 랭군님이 Trasactional.readonly를 사용하시는 덕에 저도 같이 삽질 좀 했네요.^ㅋㅋ 고맙습니다.


2010/8/26 Sungchul Park <gyu...@gmail.com>
--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--

Sungchul Park

unread,
Aug 26, 2010, 3:50:33 AM8/26/10
to ks...@googlegroups.com
재미있네요.

제가 방금 오라클에 문의 한 결과 Oracle JDBC Driver는 setReadOnly를 지원하지 않는다는 군요.ㅠㅠ

완전 삽질하게 했습니다.ㅠㅠ
그냥 지원 안한다고 JavaDoc에 넣어주면 얼마나 좋을 까...ㅠㅠ

2010/8/26 Sungchul Park <gyu...@gmail.com>

여러 자료를 이후에 검색해본 결과 JDBC Vendor에 따라 Connection을 구현 할 때 readyOnly=true이면 Exception을 내거나 하는 식으로 지원을 하는데 이는 Vendor의 구현에 따라 다르다고 하는군요.


결과 적으로 readOnly는 Vendor에 따라 다르다고 볼 수 있을 것 같습니다.

저도 이 부분이 의심스럽더군요.
JdbcConnection의 readonly 기능이 구현안되었다면 exception이 안 일어나니까요.
그런데 어떤 DB를 사용하신 건가요?

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으) 로 이메일을 보내세요.

그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에 서 그룹을 방문하세요.

Kuwon Kang

unread,
Aug 26, 2010, 3:52:07 AM8/26/10
to ks...@googlegroups.com
이 플젝에 오라큰 SE가 상주하고 있는데 ㅎㅎ 내부 시스템 통해서 같이 확인해보니
지원 안한다고 나오네요.ㅎㅎ

과거에 되었다면 버전 차이일 수도 있을 것 같구요..


2010/8/26 Sungchul Park <gyu...@gmail.com>

Sungchul Park

unread,
Aug 26, 2010, 3:52:38 AM8/26/10
to ks...@googlegroups.com
10. 8. 26. 오후 4:50, Kuwon Kang 쓴 글:

> JDBC또는 RDMBS의 문제일 수 있겠죠. 정확한건 오라클이 어떻게 구현했느냐
> 에 따라 다를 것 같습니다.
>
> 하여간 랭군님이 Trasactional.readonly를 사용하시는 덕에 저도 같이 삽질
> 좀 했네요.^ㅋㅋ 고맙습니다.
>
>
그런데 신기하네요. 전 분명히 오라클에서 read only를 썼었거든요...;;;

직접 쿼리를 날려서 설정했던 것일까요? ㅠㅠ

Sungchul Park

unread,
Aug 26, 2010, 3:54:39 AM8/26/10
to ks...@googlegroups.com

> 이 플젝에 오라큰 SE가 상주하고 있는데 ㅎㅎ 내부 시스템 통해서 같이 확
> 인해보니
> 지원 안한다고 나오네요.ㅎㅎ
>
> 과거에 되었다면 버전 차이일 수도 있을 것 같구요..
>
오라클 JDBC Driver가 뒷걸음질치는 일이 종종있지만 아마 제 착각인 듯 합니다.
set transaction read only 명령을 썼던 걸 헛갈렸나봐요.;;

미랭군

unread,
Aug 26, 2010, 4:07:03 AM8/26/10
to Korea Spring User Group
흑..그럼 오라클이 read only 기능을 업뎃해야 사용할 수 있는건가요?

어쨌든 다들 저때문에 삽질하게 만들어서 죄송합니다ㅠ

이부분은 그냥 넘어가야겠네요..

미랭군

unread,
Aug 26, 2010, 4:19:01 AM8/26/10
to Korea Spring User Group
아 한가지 궁금한건 MySQL이나 인포믹스 등 다른 타 DB에선

지원을 하는지 알고 싶네여..

대부분이 오라클이지만 인포믹스를 쓰는 회사도 몇개 있어서..

혹시 인포믹스 사용하시는 분 없으신가여?

> > set transaction read only 명령을 썼던 걸 헛갈렸나봐요.;;- 원본 텍스트 숨기기 -

백기선

unread,
Aug 26, 2010, 5:12:38 AM8/26/10
to ks...@googlegroups.com
테스트가 없길래 만들어서 해봤습니다.
DB는 오라클은 귀찮아서 PostgreSQL로.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testContext.xml")
public class CommonDAOTest {
@Autowired ICommonDAO commonDAO;
@Test
public void di(){
assertNotNull(commonDAO);
HashMap<String, String> param = new HashMap<String, String>();
param.put("ba_id", "1");
param.put("ba_nm", "1nm");
commonDAO.saveCode(param);
}

}

간단하죠.

<?xml version="1.0" encoding="UTF-8"?>

<context:property-placeholder location="classpath:/testResources.properties" />

<context:component-scan base-package="base" />

<bean id="oracleDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}"/>
</bean>

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:/sqlMapConfig.xml" />
<property name="dataSource" ref="oracleDataSource" />
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="oracleDataSource" />
</bean>

<tx:annotation-driven />

</beans>


이건 테스트용 설정 파일

# FileUpload(Size MB)
maxMemorySize = 1
maxReqeustSize = 2048
tempDirectory = /intra/upload/daims/temp
saveDirectory = /intra/upload/daims/save
#tempDirectory = D:\\temp
#saveDirectory = D:\\save

## JDBC DATASOURCE
driverClassName = org.postgresql.Driver

# External Connetion(Local server > real DB)
url = jdbc:postgresql://localhost/spring30

# Innternal Connetion(Real server > real DB)
#url = jdbc:oracle:thin:@0.0.0.0:1530:skb

username = spring30
password = spring30

이건 테스트용 설저이 담긴 propeties

테스트 실행결과는..

[2010-08-26 18:07:16] DEBUG [DirtiesContextTestExecutionListener.java.afterTestMethod():86] After test method: context [[TestContext@fa7e74 testClass = CommonDAOTest, locations = array<String>['classpath:/testContext.xml'], testInstance = base.common.dao.CommonDAOTest@183f74d, testMethod = di@CommonDAOTest, testException = org.springframework.jdbc.UncategorizedSQLException: SqlMapClient operation; uncategorized SQLException for SQL []; SQL state [25006]; error code [0];   
--- The error occurred in base/common/sqlmap/commonDAO.xml.  
--- The error occurred while applying a parameter map.  
--- Check the common.saveCode-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: org.postgresql.util.PSQLException: ERROR: transaction is read-only; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred in base/common/sqlmap/commonDAO.xml.  
--- The error occurred while applying a parameter map.  
--- Check the common.saveCode-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: org.postgresql.util.PSQLException: ERROR: transaction is read-only]], class dirties context [false], class mode [null], method dirties context [false].
[2010-08-26 18:07:16] DEBUG [DirtiesContextTestExecutionListener.java.afterTestClass():113] After test class: context [[TestContext@fa7e74 testClass = CommonDAOTest, locations = array<String>['classpath:/testContext.xml'], testInstance = [null], testMethod = [null], testException = [null]]], dirtiesContext [false].
[2010-08-26 18:07:16] INFO [AbstractApplicationContext.java.doClose():978] Closing org.springframework.context.support.GenericApplicationContext@15d56d5: startup date [Thu Aug 26 18:07:15 KST 2010]; root of context hierarchy
[2010-08-26 18:07:16] DEBUG [AbstractBeanFactory.java.doGetBean():241] Returning cached instance of singleton bean 'lifecycleProcessor'
[2010-08-26 18:07:16] INFO [DefaultSingletonBeanRegistry.java.destroySingletons():421] Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@120bf2c: defining beans [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,commonAction,commonDAO,commonService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,oracleDataSource,sqlMapClient,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor]; root of factory hierarchy
[2010-08-26 18:07:16] DEBUG [DefaultSingletonBeanRegistry.java.destroyBean():476] Retrieved dependent beans for bean 'commonDAO': [base.common.dao.CommonDAOTest]
[2010-08-26 18:07:16] DEBUG [DisposableBeanAdapter.java.destroy():172] Invoking destroy() on bean with name 'oracleDataSource'


이렇게 테스트를 해봐야 직성이 풀리는 편이라서...
설정만 바꿔서 오라클로 해보셔요.

여기서 잠깐 퀴즈
테스트 코드를 다음과 같이 바꾸면.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testContext.xml")
@Transactional
public class CommonDAOTest {
@Autowired ICommonDAO commonDAO;
@Test
public void di(){
assertNotNull(commonDAO);
HashMap<String, String> param = new HashMap<String, String>();
param.put("ba_id", "1");
param.put("ba_nm", "1nm");
commonDAO.saveCode(param);
}

}

read-only 관련 에러가 발생하지 않습니다. 그 이유는 무엇일까요?
O.B님의 질문은 바로 이것과 관련이 있다고 짐작하는데.... 과연.. 




2010년 8월 26일 오후 5:19, 미랭군 <devz...@gmail.com>님의 말:

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--
좋은 하루 되세요~
Reply all
Reply to author
Forward
0 new messages