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();
}
}
JdbcBatchItemWriter
JdbcBatchItemWriterBuilder
columnMapped
์ค์ : <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.java
public 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 ๋ธ๋ก๊ทธ