2012-07-27 3 views
1

첫째, 응용 프로그램이 여러 JDBC 데이터 소스를 가지고 있기 때문에 선언적 인 @Transactional 접근 방식을 사용할 수 없습니다. 세부 사항을 지키고 싶지는 않지만 DAO 메소드가 올바른 데이터 소스로 전달되었다고 말하는 것으로 충분합니다. 논리를 수행하십시오. 모든 JDBC 데이터 소스는 동일한 스키마를 가지고 있으며 ERP 시스템에 대한 나머지 서비스를 제공함에 따라 구분됩니다.spring JdbcTemplate을 read_uncommitted으로 가져 오려면 어떻게해야합니까?

이 레거시 시스템으로 인해 제어 할 권한이없는 오래 살아있는 잠금 된 레코드가 많아서 더러운 읽기를 원합니다. 나는 다음을 수행 할 JDBC를 사용

: 보일러 플레이트의

private Customer getCustomer(DataSource ds, String id) { 
    Customer c = null; 
    PreparedStatement stmt = null; 
    Connection con = null; 
    try { 
     con = ds.getConnection(); 
     con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); 
     stmt = con.prepareStatement(SELECT_CUSTOMER); 
     stmt.setString(1, id); 
     ResultSet res = stmt.executeQuery(); 
     c = buildCustomer(res); 
    } catch (SQLException ex) { 
     // log errors 
    } finally { 
     // Close resources 
    } 
    return c; 
} 

좋아, 많은 '나는 알고있다. 그래서 나는 봄을 사용하고 있기 때문에 JdbcTemplate을 시험해 보았습니다.

사용 JdbcTemplate을

private Customer getCustomer(JdbcTemplate t, String id) { 
    return t.queryForObject(SELECT_CUSTOMER, new CustomerRowMapper(), id); 
} 

훨씬 좋네요

,하지만 여전히 기본 트랜잭션 격리를 사용하고. 나는 어떻게 든 이것을 바꿀 필요가있다. 그래서 나는 TransactionTemplate을 사용하는 것에 대해 생각했다.

private Customer getCustomer(final TransactionTemplate tt, 
          final JdbcTemplate t, 
          final String id) { 
    return tt.execute(new TransactionCallback<Customer>() { 
     @Override 
     public Customer doInTransaction(TransactionStatus ts) { 
      return t.queryForObject(SELECT_CUSTOMER, new CustomerRowMapper(), id); 
     } 
    }); 
} 

그러나 여기서는 트랜잭션 격리를 어떻게 설정합니까? 콜백이나 어디서나 이것을 찾을 수있는 TransactionTemplate을 찾을 수 없습니다.

Spring In Action 제 3 판에서는 트랜잭션에 관한 장에서 주석이있는 선언적 트랜잭션을 계속 사용하고 있지만 언급 한 바와 같이 이것을 DAO로 사용할 수는 없습니다. 어떤 경우에는 국가 코드에서 제공되는 인수를 기반으로 사용할 데이터 소스를 런타임에 결정해야합니다.

도움을 주시면 감사하겠습니다.

답변

0

저는 처음에 DataSourceTransactionManager을 사용하여이 문제를 직접 해결했습니다.하지만 처음 보일러 플레이트를 많이 절약하지는 못했을 것 같습니다. 비록 내가 여전히 도움을 줄 수는 없지만 더 간단한 방법이 있어야한다고 느낄지라도, 나를 틀리게하지 말라. 나는 읽기 작업을 할 필요가 없다. 나는 단지 격리를 설정하기를 원한다.

private Customer getCustomer(final DataSourceTransactionManager txMan, 
          final JdbcTemplate t, 
          final String id) { 
    DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 
    def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED); 

    TransactionStatus status = txMan.getTransaction(def); 
    Customer c = null; 
    try { 
     c = t.queryForObject(SELECT_CUSTOMER, new CustomerRowMapper(), id); 
    } catch (Exception ex) { 
     txMan.rollback(status); 
     throw ex; 
    } 
    txMan.commit(status); 
    return c; 
} 

저는 더 나은 방법이 있어야한다고 생각하기 때문에 잠시 동안이 질문에 답을주지 않을 것입니다.

TransactionTemplate 여기 당신을하는 데 도움이, 당신이 적절하게 구성해야 사용 Spring 3.1.x Documentation - Chapter 11 - Transaction Management

1

를 참조하십시오. 트랜잭션 템플리트에는 트랜잭션 구성도 들어 있습니다. 실제로 TransactionTemplateDefaultTransactionDefinition까지 확장됩니다.

구성 어딘가에 이렇게해야합니다.

<bean id="txTemplate" class=" org.springframework.transaction.support.TransactionTemplate"> 
    <property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/> 
    <property name="readOnly" value="true" /> 
    <property name="transactionManager" ref="transactionManager" /> 
</bean> 

당신은 당신이 당신이 게시 TransactionTemplate 기반의 코드를 사용할 수 있어야 클래스에이 빈을 주입하면

는/이전했습니다.

그러나 코드를 정리할 수있는 더 멋진 솔루션이있을 수 있습니다. 내가 작업 한 프로젝트 중 하나에 대해, 우리는 당신과 비슷한 설정을했습니다 (단일 어플리케이션 다중 데이터베이스). 이를 위해 우리는 기본적으로 필요한 경우 데이터 소스를 전환하는 스프링 코드를 작성했습니다. 자세한 내용은 here을 참조하십시오.

응용 프로그램에서 멀리 가져 오거나 과도하게 사용하면 Spring의 AbstractRoutingDataSource을 사용해 볼 수도 있습니다.이 키는 조회 키 (사례의 국가 코드)를 기반으로 사용할 적절한 데이터 소스를 선택합니다.

두 가지 솔루션 중 하나를 사용하면 스프링 declarative transactionmanagement 접근 방식을 사용할 수 있습니다 (코드를 상당히 정리해야 함).

+0

이렇게하면 각 데이터베이스와 각 격리에 대해 여러 txTemplate을 구성해야합니까? 따라서 6 개의 데이터베이스로 쓰기 가능 격리 및 읽기 전용 더티 격리를 원한다면 12 txTemplates가 필요합니까? –

+0

필요할 때 직접 생성하거나 구성하면 transactionmanager를 전달하고 이에 따라 구성을 설정해야합니다. 최선의 해결책은 Spring의 선언적 트랜잭션 관리 (및 코드 정리 작업)를 활용할 수있는 방법으로 AbstractRoutingDataSource를 사용하는 것입니다. –

0

org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy 인 프록시 데이터 소스를 정의하고 트랜잭션 분리 레벨을 설정하십시오. setter 또는 생성자를 통해 실제 데이터 소스를 주입합니다.

 
<bean id="yourDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"> 
    <constructor-arg index="0" ref="targetDataSource"/> 
    <property name="defaultTransactionIsolationName" value="TRANSACTION_READ_UNCOMMITTED"/> 
</bean> 
관련 문제