ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • cannot change the executor type when there is an existing transaction
    Spring 2019. 4. 10. 15:06

    Spring Mybatis 사용 시 ExecutorType.Simple / ExecutorType.Batch 2개를 주요로 사용하고 있는데, 

     

    해당 사용 간 이슈 때문에 발생한 사례이다.

     

     

    1. 현재 사내에서는 ExecutorType.Batch 를 사용하고 있고, Mapper에서는 foreach에 대한 구문을 일절 사용하지 않고 있다. ( sessionFactory에서 제어하는 batch로 처리하는 형태이기 때문에 그냥 안사용하는 사람이 많다고 한다... 왜그런진 모름 )

     

    2. @Async Component Method 처리된 내역이 존재하면서 이슈가 발생

     

     

    [Process]

     

    ( A method )

    List<String> a = Sqlsession.selsectList(Select Sql);

     

    ( B method )

    SqlSession.update(Update Sql , a );

     

    B method를 호출

     

    ( C method )

    @Async 

    List<String> a = Sqlsession.selsectList(Select Sql);

     

    그 후 별도의 @Async 한 method C method 를 호출 

     

     

    하는 형태인데.

     

    B method에서는 Update 문만 존재하고, C method에서는 Async 처리되어 개별적으로 처리되는 형태.

     

    이때 B method에서 excetion이 생겼을 때 C method에서 exction이 잡히는 현상이 생김. 

     

    Spring ExecutorType Batch에서는 Select를 만나기 전까지는 flush가 되지 않으니...  exception이 엉뚱한 대에서 발생하는 경우..

     

    이 때문에 위와 같은 사례를 찾게됨.

     

    "cannot change the executor type when there is an existing transaction"

     

    이것을 해결하기 위해서 해결해야하는 숙제는

     

    Sqlsession은 1개의 transction에서는 2개 이상의 Executortype을 사용 할 수 없다라고 하는 에러인데..

     

    찾아보니.. 아래의 곳에서 해결책을 찾음

     

    https://github.com/mybatis/old-google-code-issues/issues/772

    DataSourceUtils.getConnection(DataSource);
    SqlSession openSession(ExecutorType execType, Connection connection);

     

    Spring security 에서 DatasourceUtils.getconnection으로 datasource를 가지고 현재 맺은 커넥션을 가져와서

     

    물려주면, opensession으로 exectortype을 simple/batch로 처리가능하고, 1개의 트렌젝션에서 2개이상의 exectortype을 설정이 가능하단 소리.

     


     

     

    이게 왜 된다고 그랬는지 모르겠다.

     

    갓 구글에서 그것도 깃허브 클로즈 까지 시켜둔 사항인데... 하... 설마해서 mybatis-2.0.1까지 뒤져봤건만 변경된 사항은 없다.

     

    spring transction manager은 1개의 transction에서 2개이상의 형태의 executor type 사용은 금지하고있나보다...

     

     

    public class SpringManagedTransactionFactory implements TransactionFactory {
    
     public Transaction newTransaction(Connection conn) {
            throw new UnsupportedOperationException("New Spring transactions require a DataSource");
        }
        
    }

    잘따라가다보면 SpringManageSpringManagedTransactionFactory 에서 위와같은 코드와 마주치게 되는데, 그냥 throw

     

    new 로 팅겨버리게 처리해놓고있다. 저럴꺼면 왜 사람설레게 Connection을 파라미터로 받을수있게 설정한거지?

     

    휴...만약 내가 잘못분석한거였음 좋겠다.... 

     

    제발... 

     


     

    다시 내용을 찬찬히 읽어보니 내가 영어를 못하는 멍청한놈이여서 그런거였나보다.

     

    Just realized, that the SqlSessionFactoryBean creates the SqlSessionFactory with SpringManagedTransactionFactory, which in turn will use DataSourceUtils.getConnection(), so I think, changing the key is enough.

     

    보아하니 

     

    //SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, DataSourceUtils.getConnection(dataSource));
    SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);

    DataSource는 필요없고 ( Conection ) SpringManagedTransactionFactory내에 가보면

     

    public SpringManagedTransaction(DataSource dataSource) {
            Assert.notNull(dataSource, "No DataSource specified");
            this.dataSource = dataSource;
        }

    이런 내용이 있는데, dataSource를 동일하게 맞춰주니, 처리 가능하다라는 뜻인거 같다.

     

    갓구글님 의심해서 미안합니다.

    'Spring' 카테고리의 다른 글

    Spring AOP  (0) 2019.05.10
    Spring Mybatis Batch Processing  (0) 2019.04.10
    웹페이지에서 Layout 처리 하기 위하여 표기 방법  (0) 2017.06.12
    Json Date Log를 보기 쉽게 하는법  (0) 2017.06.12
    Spring Boot Banner 처리 하기  (0) 2017.06.12

    댓글

Designed by black7375.