ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 7. MyBatisPagingItemReader로 DB내용을 읽고, MyBatisItemWriter로 DB에 쓰기
    Spring/Spring Batch 2024. 11. 18. 19:51

    MyBatis는 자바 기반의 SQL Mapper로, 애플리케이션에서 데이터베이스와 상호작용하기 위한 도구입니다. 주로 SQL 문을 직접 작성하고 이를 자바 코드와 연결하는 데 사용됩니다.

     

    1. MyBatisItemReader

     

    MyBatisPagingItemReader Spring Mybatis에서 제공하는 ItemReader 인터페이스를 구현하는 클래스이다.

    MyBatis의 Object Relation Mapper를 이용하며 다음과 같은 특징을 가지고 있다.

    장점:

    • 간편한 설정: MyBatis 쿼리 매퍼를 직접 활용하여 데이터를 읽을 수 있어 설정이 간편하다.
    • 쿼리 최적화: MyBatis의 다양한 기능을 활용하여 최적화된 쿼리를 작성할 수 있다.
    • 동적 쿼리 지원: 런타임 시 조건에 따라 동적으로 쿼리를 생성할 수 있다.

    단점:

    • MyBatis 의존성: MyBatis 라이브러리에 의존해야 한다.
    • 커스터마이징 복잡: Chunk-oriented Processing 방식과 비교했을 때 커스터마이징이 더 복잡할 수 있다.

    2. MyBatisPagingItemReader 작성하기

    	@Bean
    	public MyBatisPagingItemReader<Customer> myBatisItemReader() throws Exception {
    
    		return new MyBatisPagingItemReaderBuilder<Customer>()
    			.sqlSessionFactory(sqlSessionFactory)
    			.pageSize(CHUNK_SIZE)
    			.queryId("com.schooldevops.springbatch.batchsample.jobs.selectCustomers")
    			.build();
    	}

     

    • SqlSessionFactory: MyBatis 설정 정보 및 SQL 쿼리 매퍼 정보를 담고 있는 객체이다.
    • QueryId: 데이터를 읽을 MyBatis 쿼리 ID이다.
      • 실행 할 쿼리 xml의 mapper의 ID
    • PageSize: 페이징 쿼리를 위한 페이지 크기를 지정한다.

    3. query 작성하기

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.schooldevops.springbatch.batchsample.jobs">
    
        <resultMap id="customerResult" type="com.schooldevops.springbatch.batchsample.config.Customer">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="age" column="age"/>
            <result property="gender" column="gender"/>
        </resultMap>
    
        <select id="selectCustomers" resultMap="customerResult">
            SELECT id, name, age, gender
            FROM customer2
                     LIMIT #{_skiprows}, #{_pagesize}
        </select>
    </mapper>

     

    • resultMap는 select 쿼리 실행 결과를  table column과 객체를 매핑한다.
    •  _skiprows: 오프셋. 쿼리 별과에서 얼마나 스킵할지 지정. pageSize를 지정했다면 자동으로 계산
    •  _pagesize: 한 번에 가져올 페이지 지정

    4. 의존성 추가

    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
    implementation 'org.mybatis:mybatis:3.5.16'
    implementation 'org.mybatis:mybatis-spring:3.0.3'

    build.gradle에 mybatis 의존성을 추가한다.

     


    5. mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <settings>
            <setting name="mapUnderscoreToCamelCase" value="true" />
            <setting name="multipleResultSetsEnabled" value="true" />
            <setting name="callSettersOnNulls" value="true"/>
        </settings>
    </configuration>

     

    mybatis 설정 xml을 classpath에 추가한다.

     

    자세한 설정은 아래 참고

    https://mybatis.org/mybatis-3/ko/configuration.html

     

    mybatis – 마이바티스 3 | 매퍼 설정

    매퍼 설정 마이바티스 XML 설정파일은 다양한 설정과 프로퍼티를 가진다. 문서의 구조는 다음과 같다.: configuration properties 이 설정은 외부에 옮길 수 있다. 자바 프로퍼티 파일 인스턴스에 설정할

    mybatis.org


    6. 전체 코드 보기

    @Slf4j
    @Configuration
    @RequiredArgsConstructor
    public class MyBatisReaderJobConfig {
    
    	/**
    	 * CHUNK 크기를 지정한다.
    	 */
    	public static final int CHUNK_SIZE = 2;
    	public static final String ENCODING = "UTF-8";
    	public static final String MYBATIS_CHUNK_JOB = "MYBATIS_CHUNK_JOB";
    
    	private final DataSource dataSource;
    	private final SqlSessionFactory sqlSessionFactory;
    
    	@Bean
    	public MyBatisPagingItemReader<Customer> myBatisItemReader() throws Exception {
    
    		return new MyBatisPagingItemReaderBuilder<Customer>()
    			.sqlSessionFactory(sqlSessionFactory)
    			.pageSize(CHUNK_SIZE)
    			.queryId("com.schooldevops.springbatch.batchsample.jobs.selectCustomers")
    			.build();
    	}
    
    
    	@Bean
    	public FlatFileItemWriter<Customer> customerCursorFlatFileItemWriter() {
    		return new FlatFileItemWriterBuilder<Customer>()
    			.name("customerCursorFlatFileItemWriter")
    			.resource(new FileSystemResource("./customer_new_v4.csv"))
    			.encoding(ENCODING)
    			.delimited().delimiter("\t")
    			.names("Name", "Age", "Gender")
    			.build();
    	}
    
    
    	@Bean
    	public Step customerJdbcCursorStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception {
    		log.info("------------------ Init customerJdbcCursorStep -----------------");
    
    		return new StepBuilder("customerJdbcCursorStep", jobRepository)
    			.<Customer, Customer>chunk(CHUNK_SIZE, transactionManager)
    			.reader(myBatisItemReader())
    			.processor(new CustomerItemProcessor())
    			.writer(customerCursorFlatFileItemWriter())
    			.build();
    	}
    
    	@Bean
    	public Job customerJdbcCursorPagingJob(@Qualifier("customerJdbcCursorStep") Step customerJdbcCursorStep, JobRepository jobRepository) {
    		log.info("------------------ Init customerJdbcCursorPagingJob -----------------");
    		return new JobBuilder(MYBATIS_CHUNK_JOB, jobRepository)
    			.incrementer(new RunIdIncrementer())
    			.start(customerJdbcCursorStep)
    			.build();
    	}
    }
    • 여기서는 MyBatis를 이용하여, 페이징을 이용한 청크단위 처리를 수행했다.
    • Mybatis는 쿼리를 직접 작성하고, 쿼리 내용직접 최적화 할수 있는 장점이 있다.
    • pageSize를 이용하면 자동으로 offset과 pagesize를 자동으로 계산하여 페이징 처리를 수행해준다.

    7. MyBatisItemWriter

       @Bean
        public MyBatisBatchItemWriter<Customer> mybatisItemWriter() {
            return new MyBatisBatchItemWriterBuilder<Customer>()
                    .sqlSessionFactory(sqlSessionFactory)
                    .statementId("com.schooldevops.springbatch.batchsample.jobs.insertCustomers")
                    .build();
        }
    • MyBatisBatchItemWriter Spring Batch에서 제공하는 ItemWriter 인터페이스를 구현하는 클래스이다.
    • 데이터를 MyBatis를 통해 데이터베이스에 저장하는 데 사용된다.

    구성 요소

    • SqlSessionTemplate: MyBatis SqlSession 생성 및 관리를 위한 템플릿 객체이다.
    • SqlSessionFactory: SqlSessionTemplate 생성을 위한 팩토리 객체이다.
    • StatementId: 실행할 MyBatis SQL 맵퍼의 스테이tement ID이다.
    • ItemToParameterConverter: 객체를 ParameterMap으로 변경할수 있다.

    장점

    • ORM 연동: MyBatis를 통해 다양한 데이터베이스에 데이터를 저장할 수 있다.
    • SQL 쿼리 분리: SQL 쿼리를 Java 코드로부터 분리하여 관리 및 유지 보수가 용이하다.
    • 유연성: 다양한 설정을 통해 원하는 방식으로 데이터를 저장할 수 있다.

    단점

    • 설정 복잡성: MyBatis 설정 및 SQL 맵퍼 작성이 복잡할 수 있다.
    • 데이터베이스 종속: 특정 데이터베이스에 종속적이다.
    • 오류 가능성: 설정 오류 시 데이터 손상 가능성이 있다.
       <insert id="insertCustomers" parameterType="com.schooldevops.springbatch.batchsample.config.Customer">
            INSERT INTO customer2(name, age, gender) VALUES (#{name}, #{age}, #{gender});
        </insert>

     

    데이터를 추가 하기 위한 insert 쿼리를 작성한다,

     

        @Bean
        public MyBatisBatchItemWriter<Customer> mybatisItemWriter() {
            return new MyBatisBatchItemWriterBuilder<Customer>()
                    .sqlSessionFactory(sqlSessionFactory)
                    .statementId("com.schooldevops.springbatch.batchsample.jobs.insertCustomers")
                   .itemToParameterConverter(item -> {
                       Map<String, Object> parameter = new HashMap<>();
                       parameter.put("name", item.getName());
                       parameter.put("age", item.getAge());
                       parameter.put("gender", item.getGender());
                       return parameter;
                   })
                    .build();
        }

    Map을 이용하여 위와 같이 작성이 가능하다.

    댓글

Designed by Tistory.