ItemWriter๋ ์ถ๋ ฅ ๊ธฐ๋ฅ์ด๋ค.
์ด์ฐฝ๊ธฐ Spring Batch๋ item์ ํ๋์ฉ ๋ค๋ฃจ์์ง๋ง, ํ์ฌ๋ chunk ๋จ์๋ก ๋ฌถ์ธ item List๋ฅผ ๋ค๋ฃฌ๋ค.
Reader์ read()๋ Item์ ํ๋ ๋ฐํํ๋ ๋ฐ๋ฉด, Writer์ write()๋ ์ธ์๋ก Item List๋ฅผ ๋ฐ๋๋ค.
์ฆ, Reader์ Processor๋ฅผ ๊ฑฐ์ณ ์ฒ๋ฆฌ๋ Item์ Chunk๋จ์ ๋งํผ ์์ ๋ค ์ด๋ฅผ Writer์๊ฒ ์ ๋ฌํ๋ค.
Java์์๋ JDBC๋๋ ORM์ ์ฌ์ฉํ์ฌ RDBMS์ ์ ๊ทผํ๋ค.
Spring Batch๋ JDBC์ ORM ๋ชจ๋ Writer๋ฅผ ์ ๊ณตํ๋ค.
Writer๋ Chunk๋จ์์ ๋ง์ง๋ง ๋จ๊ณ์ด๋ฉฐ ํญ์ ๋ง์ง๋ง์ Flush๋ฅผ ํด์ค์ผ ํ๋ค.
Writer๊ฐ ๋ฐ์ ๋ชจ๋ Item์ด ์ฒ๋ฆฌ๋ ํ, Spring Batch๋ ํ์ฌ ํธ๋์ญ์
์ ์ปค๋ฐํ๋ค.
Database Writer์ ์ข ๋ฅ๋ ๋ค์๊ณผ ๊ฐ๋ค. ๋ค์ ์ค boldํ์ ๋ ํญ๋ชฉ์ ์์๋ณด๊ฒ ๋ค.
JdbcBatchItemWriter๋ ๋ค์๊ณผ ๊ฐ์ด ๋์ํ๋ค.
1. ChunkSize๋งํผ Query ๋ชจ์ผ๊ธฐ
2. ๋ชจ์๋์ Query ํ๋ฒ์ ์ ์ก
3. ๋ฐ์ ์ฟผ๋ฆฌ๋ค Database์์ ์คํ
JdbcBatchItemWriterJobConfiguration.java@Slf4j
@RequiredArgsConstructor
@Configuration
public class JdbcBatchItemWriterJobConfiguartion {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final DataSource dataSource;
private static final int chunkSize = 10;
@Bean
public Job jdbcBatchItemWriterJob() {
return jobBuilderFactory.get("jdbcBatchItemWriterJob")
.start(jdbcBatchItemWriterStep())
.build();
}
@Bean
public Step jdbcBatchItemWriterStep() {
return stepBuilderFactory.get("jdbcBatchItemWriterStep")
.<Pay, Pay>chunk(chunkSize)
.reader(jdbcBatchItemWriterReader())
.writer(jdbcBatchItemWriter())
.build();
}
@Bean
public JdbcCursorItemReader<Pay> jdbcBatchItemWriterReader() {
return new JdbcCursorItemReaderBuilder<Pay>()
.fetchSize(chunkSize)
.dataSource(dataSource)
.rowMapper(new BeanPropertyRowMapper<>(Pay.class))
.sql("SELECT id, amount, tx_name, tx_date_time FROM pay")
.name("jdbcBatchItemWriterReader")
.build();
}
// beanMapped()๋ฅผ ์ฌ์ฉํ ๋๋ ํ์
@Bean
public JdbcBatchItemWriter<Pay> jdbcBatchItemWriter() {
// ColumnMapped()
// return new JdbcBatchItemWriterBuilder<Map<String, Object>>()
// .dataSource(dataSource)
// .sql("insert into pay2(amount, tx_name, tx_date_time) values (:amount, :txName, :txDateTime)")
// .columnMapped()
// .build();
// BeanMapped()
return new JdbcBatchItemWriterBuilder<Pay>()
.dataSource(dataSource)
.sql("insert into pay2(amount, tx_name, tx_date_time) values (:amount, :txName, :txDateTime)")
.beanMapped()
.build();
}
}
JdbcBatchItemWriterJdbcBatchItemWriterBuildercolumnMapped ์ค์ : <Key, Value> ๊ธฐ๋ฐ์ insert SQL Values ๋งคํJdbcBatchItemWriterBuilder<Map<String, Object>>()beanMapped ์ค์ : Pojo ๊ธฐ๋ฐ์ insert SQL Values ๋งคํJdbcBatchItemWriterBuilder<Pay>()ItemWriter๋ฅผ ํ์ฉํ์ฌ pay2๋ผ๋ ํ
์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ ๊ฒ์ด๋ค.
mysql์ ์ ์ํ์ฌ pay2 ํ
์ด๋ธ์ ๋ง๋ค์ด์ค๋ค.
create table pay2 (
id bigint not null auto_increment,
amount bigint,
tx_name varchar(255),
tx_date_time datetime,
primary key (id)
) engine = InnoDB;
./gradlew build -x test
java -jar ./build/libs/*.jar --job.name=jdbcBatchItemWriterJob
pay2ํ
์ด๋ธ์ ํ์ธํด๋ณด๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ค์ด๊ฐ ๊ฒ์ ํ์ธํ ์ ์๋ค.
ORM์ ์ฌ์ฉํ ์ ์๋ JpaItemWriter์ด๋ค.
Writer์ ์ ๋ฌํ๋ ๋ฐ์ดํฐ๊ฐ Entity ํด๋์ค๋ผ๋ฉด JpaItemWriter๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
JpaItemWriter๋ ๋์ด์จ Entity๋ฅผ Database์ ๋ฐ์ํ๋ค.
์ฆ, JpaItemWriter๋ Entity ํด๋์ค๋ฅผ ์ ๋ค๋ฆญ ํ์
์ผ๋ก ๋ฐ์์ผํ๋ค.
JpaItemWriterJobConfiguration.java@Slf4j
@RequiredArgsConstructor
@Configuration
public class JpaItemWriterJobConfiguration {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final EntityManagerFactory entityManagerFactory;
private static final int chunkSize = 10;
@Bean
public Job jpaItemWriterJob() {
return jobBuilderFactory.get("jpaItemWriterJob")
.start(jpaItemWriterStep())
.build();
}
@Bean
public Step jpaItemWriterStep() {
return stepBuilderFactory.get("jpbItemWriterStep")
.<Pay, Pay2>chunk(chunkSize)
.reader(jpaItemWriterReader())
.processor(jpaItemProcessor())
.writer(jpaItemWriter())
.build();
}
@Bean
public JpaPagingItemReader<Pay> jpaItemWriterReader() {
return new JpaPagingItemReaderBuilder<Pay>()
.name("jpaItemWriterReader")
.entityManagerFactory(entityManagerFactory)
.pageSize(chunkSize)
.queryString("SELECT p FROM Pay p")
.build();
}
@Bean
public ItemProcessor<Pay, Pay2> jpaItemProcessor() {
return pay -> new Pay2(pay.getAmount(), pay.getTxName(), pay.getTxDateTime());
}
@Bean
public JpaItemWriter<Pay2> jpaItemWriter() {
JpaItemWriter<Pay2> jpaItemWriter = new JpaItemWriter<>();
jpaItemWriter.setEntityManagerFactory(entityManagerFactory);
return jpaItemWriter;
}
}
Pay2.java@ToString
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Pay2 {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long amount;
private String txName;
private LocalDateTime txDateTime;
public Pay2(Long amount, String txName, String txDateTime) {
this.amount = amount;
this.txName = txName;
this.txDateTime = LocalDateTime.parse(txDateTime, FORMATTER);
}
public Pay2(Long amount, String txName, LocalDateTime txDateTime) {
this.amount = amount;
this.txName = txName;
this.txDateTime = txDateTime;
}
public Pay2(Long id, Long amount, String txName, String txDateTime) {
this.id = id;
this.amount = amount;
this.txName = txName;
this.txDateTime = LocalDateTime.parse(txDateTime, FORMATTER);
}
}
Pay2Repository.javapublic interface Pay2Repository extends JpaRepository<Pay2, Long> { }
./gradlew build -x test
java -jar ./build/libs/*.jar --job.name=jpaItemWriterJob
pay2ํ
์ด๋ธ์ ์ถ๊ฐ๋ก ๋ฐ์ดํฐ๊ฐ ๋ค์ด๊ฐ ๊ฒ์ ํ์ธํ ์ ์๋ค.
Writer๋ฅผ Customํ๊ฒ ๊ตฌํํด์ผ ํ ์ผ์ ๋น๋ฒํ๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์ด๋ฌํ ๊ฒฝ์ฐ ItemWriter ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ฉด ๋๋ค.
System.out.println์ ์ญํ ์ ํ๋ Writer๋ฅผ ๋ง๋ค์ด๋ณด์.
CustomItemWriterJobConfiguration.java @Slf4j
@RequiredArgsConstructor
@Configuration
public class CustomItemWriterJobConfiguration {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final EntityManagerFactory entityManagerFactory;
private static final int chunkSize = 10;
@Bean
public Job customItemWriterJob() {
return jobBuilderFactory.get("customItemWriterJob")
.start(customItemWriterStep())
.build();
}
@Bean
public Step customItemWriterStep() {
return stepBuilderFactory.get("customItemWriterStep")
.<Pay, Pay2>chunk(chunkSize)
.reader(customItemWriterReader())
.processor(customItemWriterProcessor())
.writer(customItemWriter())
.build();
}
@Bean
public JpaPagingItemReader<Pay> customItemWriterReader() {
return new JpaPagingItemReaderBuilder<Pay>()
.name("customeItemWriterReader")
.entityManagerFactory(entityManagerFactory)
.pageSize(chunkSize)
.queryString("SELECT p FROM Pay p")
.build();
}
@Bean
public ItemProcessor<Pay, Pay2> customItemWriterProcessor() {
return pay -> new Pay2(pay.getAmount(), pay.getTxName(), pay.getTxDateTime());
}
@Bean
public ItemWriter<Pay2> customItemWriter() {
// Java8 ์ด์
return items -> {
for (Pay2 item : items) {
System.out.println(item);
}
};
// Java7 ์ดํ
// return new ItemWriter<Pay2>() {
// // ๋ค์๊ณผ ๊ฐ์ด write()๋ฅผ override๋ก ๊ตฌํํ๋ค.
// @Override
// public void write(List<? extends Pay2> items) throws Exception {
// for (Pay2 item : items) {
// System.out.println(item);
// }
// }
// };
}
}
./gradlew build -x test
java -jar .\build\libs\demo-0.0.1-SNAPSHOT.jar --job.name=customItemWriterJob
pay ํ
์ด๋ธ์ ๋ฐ์ดํฐ๊ฐ pay2๋ก ์ฒ๋ฆฌ๋์ด ์ถ๋ ฅ๋์๋ค.
๋ชจ๋ ์์ค๋ ๊นํ๋ธ์ ์ฌ๋ ค๋์๋ค.
์ฐธ๊ณ ๋งํฌ: jojoldu ๋ธ๋ก๊ทธ