2011-03-30 2 views
2

Spring 기반 웹 애플리케이션 내에서 선언적 트랜잭션 관리를 구성하려고 시도했지만 나와 협력하기를 거부했습니다.Spring Jdbc 선언적 트랜잭션이 생성되었지만 아무것도 수행하지 않음

나는 두 가지 문제가 발생 : (우리는 우리의 응용 프로그램에 필요한한다) 또는 트랜잭션이 포함되지 않고, 롤백 모든 쿼리를 야기 우리는 dataSource에 false로 defaultAutoCommit 설정

  1. 합니다.
  2. 트랜잭션이 구성되고 프록시 클래스와 트랜잭션 방식이 만들어 지지만 트랜잭션은 사용 된 것으로 나타나지 않습니다.

첫 번째 문제는 모든 개별 쿼리가 데이터베이스에서 롤백되기 때문에 오히려 혼란 스럽습니다. 여기에는 SELECT 문도 포함됩니다. 어떤 쿼리가 데이터베이스에서 롤백 될 수 있습니까? 내가하려고에 방문한 튜토리얼과 포럼의 모든에서

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:p="http://www.springframework.org/schema/p" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xmlns:context="http://springframework.org/schema/context" 
     xmlns:util="http://www.springframework.org/schema/util" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/spring-context-3.0.xsd 
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd" 
     default-autowire="byName"> 

<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) --> 
<tx:advice id="txAdvice" transaction-manager="txManager"> 
    <!-- the transactional semantics... --> 
    <tx:attributes> 
    <!-- other methods use the default transaction settings (see below) --> 
    <tx:method name="*" rollback-for="Exception" /> 
    </tx:attributes> 
</tx:advice> 

<!-- ensure that the above transactional advice runs for any execution 
of an operation defined by a service in the service package --> 
<aop:config> 
    <aop:pointcut id="serviceOperations" expression="execution(* foo.bar.service.*.*(..))"/> 
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperations"/> 
</aop:config> 

<!-- similarly, don't forget the PlatformTransactionManager --> 
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="${jdbc.driverClassName}" /> 
    <property name="url" value="${jdbc.url}" /> 
    <property name="username" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
    <property name="defaultAutoCommit" value="false" /> 
</bean> 

<bean id="fooService" class="foo.bar.service.FooService" /> 

<bean id="barService" class="foo.bar.service.BarService" /> 

<bean id="zapService" class="foo.bar.service.ZapService" /> 

</beans> 

: 두 번째 문제에 관해서는

, 트랜잭션 관리의 내 구성은 아래에 설명되어 있습니다 이 문제를 해결하면 내 구성이 정확해야한다고 생각합니다. 그러나 나는 Aop 및 Spring 트랜잭션을 완전히 이해하지 못하므로 중요한 것을 놓친 것일 수 있습니다.

위에서 언급 한 것처럼 내 서비스 클래스에 대해 생성되는 트랜잭션 방식뿐만 아니라 프록시도 로그를 통해 추적 할 수 있습니다. 그러나 실제로 응용 프로그램을 실행하고 로그를 통해 추적 할 때 DataSourceTransactionManager를 처리하는 명령문이나 트랜잭션이 작성, 커밋되고 롤백되는 트랜잭션이 표시되지 않습니다.

아무 것도 실제로 실행되지 않는 것처럼 보입니다. , 그리고 나는 많은 다른 튜토리얼을 따라 많은 다른 방법을 시도했지만 나는 항상 끔찍하게 혼란 스럽다. 그러나 항상이 상황으로 끝난다.

Log4j 속성이 DataSourceTransactionManager에서 메시지를 수신하도록 올바로 설정되어 있는지는 상당히 확실하지만, 아래에 나와 있습니다. 내 부분에 로깅 오류가 아닌지 확인하기 위해 아래에 제공하고 있습니다.

내 log4j에이 시도하고 거래를 통해 추적하려면 다음 로거 설정

:

log4j.logger.org.springframework=INFO, file 
log4j.logger.org.springframework.jdbc.datasource=DEBUG, file 
log4j.logger.org.springframework.transaction=DEBUG, file 

참고 : 나는 서비스 것을 확인 어디 한 지점에서 DEBUG에 최고 로거를 실행하고, 즉 프록시가 생성되었습니다.

어떤 일이 일어날 지 알 수있는 사람이 있습니까? 나는 오히려 그 순간에 막혔다. 나는 트랜잭션이 생성되는 것과 관련된 부분을 보았으나 사용 된 트랜잭션의 흔적은 전혀 보지 못했다.

편집 : JB Nizet의 요청에 따라

추가 정보입니다.

내 전체 응용 프로그램은 주석 기반이므로 서비스 빈에 @Service 주석이 달리고 이름 기반 자동 와이어 링을 통해 내 컨트롤러에 주입됩니다.

다음은 내 서비스 클래스 중 하나의 예제입니다 (이름은 변경되었지만 applicationContext.xml을 반영합니다).

@Service("zapService") 
public class ZapService 
{ 

    /** 
    * Data access object which performs the database look up 
    */ 
    private ZapDAO zapDAO; 

    /** 
    * Add the given zap to the database 
    * 
    * @param zap a populated zap 
    */ 
    public void processNewZap(Zap zap) 
    { 
     zapDAO.processNewZap(zap); 
    } 
} 

본인의 서비스 클래스는 컨트롤러 클래스와 dao 클래스 사이의 단순한 프록시입니다. DAO는 실제로 데이터베이스 연결을 처리하는 곳입니다.

저는 거래를 처리 할 때 서비스를 거래하는 것이 아니라, DAO 클래스를 사용하는 것이 바람직한 방법이라고 생각합니다. 내가 틀렸다면 나를 바로 잡아주세요.

ZapDAO 클래스는 아래에 요약되어 있습니다.

@Repository("zapDAO") 
public class ZapDAO 
{ 

    /** 
    * Log4j logger for this class 
    */ 
    Logger logger = Logger.getLogger(ZapDAO.class); 

    /** 
    * Spring jdbc object to handle interacting with the database 
    */ 
    private JdbcTemplate jdbcTemplate; 

    public void processNewZap(Zap zap) { 

     ... query constructing logic ... 

     this.jdbcTemplate.update(INSERT_ZAP_QUERY_SQL); 

    } 

    public void setDataSource(DataSource dataSource) 
    { 
     Assert.notNull(dataSource, "You must supply a valid data source"); 

     this.jdbcTemplate = new JdbcTemplate(dataSource); 
    } 
} 

저는 연결 및 쿼리를 처리하기 위해 jdbcTemplate을 사용합니다.

+0

서비스 bean 인스턴스를 얻는 데 사용 된 코드와 일부 서비스 bean의 코드를 표시 할 수 있습니까? dataSource를 사용하고 있습니까? 특히 DataSourceUtils.getConnection (DataSource)을 사용하여 연결을 얻으십니까? 아니면 JdbcTemplate을 사용합니까? –

+0

응답 해 주셔서 감사합니다. 요청 된 추가 정보에 대한 수정 사항을 참조하십시오. –

답변

3

내 머리카락을 찾고, 디버깅하고, 추출하는 데 몇 시간이 걸렸으므로 마침내 우연히 만났습니다. this 모든 답변을 제공 한 작은 보석.

위의 링크에 설명 된 단계를 따르면 완벽하게 작동했지만 문제는 아닌 것으로 생각됩니다. 내 응용 프로그램 콩의 모든 부모 패키지입니다

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

다음과 같이 내가 원래 내 구성 요소 검사를 선언했다 나의 파견-servlet.xml 파일 내부

. 그래서 위의 링크에서 설명한 것처럼 Spring은 applicationContext.xml의 트랜잭션 서비스 bean을 트랜잭션에 대해 알지 못하는 dispatcher-servlet.xml의 서비스 bean으로 겹쳐 쓰고있었습니다.

위의 구성 요소 스캔을 분해하여 비 트랜잭션 빈을 포함하는 폴더 만 검색했습니다.

<context:component-scan base-package="foo.bar.controller"/> 
<context:component-scan base-package="foo.bar.model"/> 
<context:component-scan base-package="foo.bar.service.display"/> 
<context:component-scan base-package="foo.bar.service.security"/> 

<!-- foo.bar.service gets scanned in applicationContext.xml and includes 
transactions so we must make sure to not include it here. The transactional beans 
will be overridden in that case --> 

예상 나는 마침내 내 로그 파일에 트랜잭션과의 DataSourceTransactionManager의 발자국을보고되면서이 내 거래 정확히 일 후. 이것은 또한 데이터베이스에서 자동 롤백의 첫 번째 초기 문제점을 수정했습니다. 나는 그것이 거래의 부족과 밀접하게 관련되어 있었음에 틀림 없다.

+0

''은 건강에 위험 할 수 있습니다. 나는 당신이 언급 한 이유 때문에 그것을 피합니다. 그러나 귀하의 솔루션을 설명하기 위해 +1. 자신의 답변을 수락 한 것으로 표시해야합니다. – skaffman

+0

주석을 처리 할 때 필자가 필요로한다는 인상하에있었습니다. 이 문제를 해결할 더 좋은 방법이 있습니까? –

+0

또한, 내 대답을 수락하기 전에 또 10 분을 기다려야 만합니다.) –

관련 문제