-
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을 이용하여 위와 같이 작성이 가능하다.
'Spring > Spring Batch' 카테고리의 다른 글
9. 입맛에 맞는 배치 처리를 위한 Custom ItemReader/ItemWriter 구현 (0) 2024.12.10 8. CompositeItemProcessor 으로 여러단계에 걸쳐 데이터 Transform하기 (0) 2024.12.02 5. JdbcPagingItemReader로 DB내용을 읽고, JdbcBatchItemWriter로 DB에 쓰기 (0) 2024.11.05 4. FlatFileItemReader로 단순 파일 읽고, FlatFileItemWriter로 파일에 쓰기 (0) 2024.11.04 3.SpringBatch ChunkModel과 TaskletModel (1) 2024.10.21