inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링 배치

DB - JdbcPagingItemReader

JdbcPagingItemReader에서 ID값이 읽어지지 않습니다.

394

코린코린

작성한 질문수 53

0

안녕하세요! 항상 좋은 강의 제공해주셔서 감사합니다.
강의를 바탕으로 실습을 하고 있는 도중 문제가 있어서 해당 부분을 문의 드리고자 글을 적습니다.
 
 
문제는 Jpa 기반 ItemReader를 사용할 경우, 객체에 정상적으로 PK값이 들어오는 것이 확인되는데, Jdbc 기반 ItemReader를 사용할 경우 PK값이 정상적으로 들어오지 않는 것이 확인됩니다.
 
ItemReader에서 값을 읽어온 후, ItemProcessor에서 전달받은 Input Chunk를 item 단위로 로그를 찍었을 때 확인한 것이라, ItemReader를 통해 DB에서 읽은 값이 객체에 맵핑이 되지 않는 것 같습니다.
 
혹시 이런 경우, 제가 어떤 부분을 잘못 설정하고 있는 것인지 조언을 부탁 드릴 수 있을까요? 아래에 주요 코드 및 실행 결과를 첨부드립니다.
 
 
@Entity 클래스
public class Customer {

@Id
@GeneratedValue
@Column(name = "customer_id")
private Long id;
private String firstName;
private String lastName;
private LocalDate birthDate;


}

 

@JpaCursorItemReader

@Bean
public ItemReader<Customer> customerJpaItemReader() {

HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("firstname", "%customer0");

return new JpaCursorItemReaderBuilder<Customer>()
.name("jpaCursorItemReader")
.entityManagerFactory(emf)
.queryString("select c from Customer c")
.maxItemCount(100)
.currentItemCount(10)
.build();
}

 

@JpaCursorItemReader 실행 결과

pk값이 정상적으로 맵핑되서 올라옵니다.

 

@JdbcPagingItemReader

    return new JdbcPagingItemReaderBuilder<Customer>()
.name("JdbcPagingItemReaderJob")
.dataSource(dataSource)
.pageSize(10)
.beanRowMapper(Customer.class)
.fetchSize(CHUNK_SIZE)
.currentItemCount(0)
.maxItemCount(100)
.selectClause("first_name, last_name, birth_date, customer_id")
.fromClause("from Customer")
.sortKeys(sortKey)
.build();
}

 

@JdbcPagingItemReader 실행 결과

실행 결과 : Id값만 짤려서 올라옵니다.

spring-boot spring-batch

답변 1

0

정수원

보다 정확한 테스트를 위해 소스 공유 부탁드립니다.

실제 제가 소스를 돌려보면 정상적으로 결과가 나오는 경우가 많기 때문에 질문자분께서 테스트 한 소스 그대로를 실행해 봐야 될 것 같습니다.

0

코린코린

바쁘실텐데 감사합니다!

아래에 SQL Injection / 엔티티 클래스 / JdbcCursorItemReaderConfig 클래스 / JpaPagingItemReaderConfig 클래스를 공유해드립니다. 강사님처럼 제가 SQL 스크립트를 작성해서 넣을 줄 몰라, JPA로 SQL Injection 컨트롤러 이용해서 웹 요청 올 때마다 엔티티 생성해서 DB에 밀어넣었습니다.

 

아래 클래스에서 JpaPagingItemReader 활성화 후 Job 수행하면 id값이 읽히는데, JdbcCursorItemReaderConfig는 id값이 읽히지 않습니다! 

 

 

@SQL Injection 위한 컨트롤러

@Controller
@RequiredArgsConstructor
public class JpaConfig {

private final JpaRepository jpaRepository;

@RequestMapping("/testdata")
@ResponseBody
public String testDataInject() {
jpaRepository.testDataInject();
return "ok";
}
}

 

@SQL Injection 위한 Repository 

@Repository
@RequiredArgsConstructor
@Transactional
public class JpaRepository {

private final EntityManager em;



@Transactional
public void testDataInject() {

for (int i = 0; i < 100; i++) {
Customer customer = Customer.builder()
.firstName("customer" + i)
.lastName(i + "customer")
.birthDate(LocalDate.now())
.build();

em.persist(customer);
}

for (int i = 0; i < 100; i++) {
Customer customer = Customer.builder()
.firstName("ali" + i)
.lastName(i + "ali")
.birthDate(LocalDate.now())
.build();
em.persist(customer);
}
for (int i = 0; i < 100; i++) {
Customer customer = Customer.builder()
.firstName("bli" + i)
.lastName(i + "bli")
.birthDate(LocalDate.now())
.build();
em.persist(customer);
}
}
}

 

 

@Entity 클래스

@Builder
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {

@Id
@GeneratedValue
@Column(name = "customer_id")
private Long id;
private String firstName;
private String lastName;
private LocalDate birthDate;


}

 

@JdbcPagingItemReader 테스트 위한 Config 클래스

//@Configuration
@RequiredArgsConstructor
public class JdbcPagingItemReaderConfig {

private final StepBuilderFactory stepBuilderFactory;
private final JobBuilderFactory jobBuilderFactory;
private final DataSource dataSource;
private final static int CHUNK_SIZE = 10;

@Bean
public Job JdbcJob() {
return jobBuilderFactory
.get("JcbcPagingItemReaderJob")
.start(step100())
.incrementer(new RunIdIncrementer())
.build();
}

@Bean
public Step step100() {
return stepBuilderFactory
.get("JcbcPagingItemReaderStep")
.<Customer, Customer>chunk(CHUNK_SIZE)
.reader(customerItemReader())
.processor(new ItemProcessor<Customer, Customer>() {
@Override
public Customer process(Customer item) throws Exception {
System.out.println("item =" + item);

return Customer.builder()
.id(item.getId())
.lastName(item.getLastName().toUpperCase(Locale.ROOT))
.firstName(item.getFirstName().toUpperCase(Locale.ROOT))
.birthDate(item.getBirthDate())
.build();
}
})
.writer(new ItemWriter<Customer>() {
@Override
public void write(List<? extends Customer> items) throws Exception {
System.out.println("=========================");
System.out.println("JDBC Paging ITEM READER WORK");
items.forEach(customer -> System.out.println("customer = " + customer));
System.out.println("=========================");
}
})
.build();
}

@Bean
public ItemReader<Customer> customerItemReader() {

HashMap<String, Order> sortKey = new HashMap<>();
sortKey.put("first_name", Order.ASCENDING);

return new JdbcPagingItemReaderBuilder<Customer>()
.name("JdbcPagingItemReaderJob")
.dataSource(dataSource)
.pageSize(2)
.beanRowMapper(Customer.class)
// .fetchSize(CHUNK_SIZE)
.currentItemCount(0)
.maxItemCount(100)
.selectClause("first_name, last_name, birth_date, customer_id")
.fromClause("from Customer")
.sortKeys(sortKey)
.build();
}
}

 

@JpaCursorItemReader 테스트 위한 Config 클래스

//@Configuration
@RequiredArgsConstructor
public class JpaCursorItemReaderConfig {

private final StepBuilderFactory stepBuilderFactory;
private final JobBuilderFactory jobBuilderFactory;
private final DataSource dataSource;
private final EntityManagerFactory emf;
private final static int CHUNK_SIZE = 100;



@Bean
public Job jpaCursorItemReaderJob() {
return jobBuilderFactory
.get("jpaCursorItemReaderJob")
.start(stepJpa())
.incrementer(new RunIdIncrementer())
.build();
}

@Bean
public Step stepJpa() {
return stepBuilderFactory
.get("jpaItemReaderStep")
.<Customer, Customer>chunk(CHUNK_SIZE)
.reader(customerJpaItemReader())
.processor(new ItemProcessor<Customer, Customer>() {
@Override
public Customer process(Customer item) throws Exception {
System.out.println("item =" + item);

return Customer.builder()
.firstName(item.getFirstName().toUpperCase(Locale.ROOT))
.lastName(item.getLastName().toUpperCase(Locale.ROOT))
.birthDate(item.getBirthDate())
.id(item.getId())
.build();
}
})
.writer(new ItemWriter<Customer>() {
@Override
public void write(List<? extends Customer> items) throws Exception {
System.out.println("=========================");
System.out.println("JPA ITEM READER WORK");
items.forEach(customer -> System.out.println("customer = " + customer));
System.out.println("=========================");
}
})
.build();

}

@Bean
public ItemReader<Customer> customerJpaItemReader() {

HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("firstname", "%customer0");

return new JpaCursorItemReaderBuilder<Customer>()
.name("jpaCursorItemReader")
.entityManagerFactory(emf)
.queryString("select c from Customer c")
.maxItemCount(100)
.currentItemCount(10)
.build();
}
}

 

스프링 배치 버전 질문

0

141

1

소스코드가 어디에 있나요?

0

122

2

트랜잭션 예외

0

101

1

질문이 있습니다.

0

141

2

ChunkListener 에서 beforeChunk 의 실행 시점 관련 질문

0

146

2

여러 JOB 설정하는법

0

158

2

강의 자료 다른 방법 있을까요?

0

164

1

JobExecution과 JobExecutionContext와의 관계

0

199

2

특정 job만 실행

1

271

1

Batch 성능 질문

0

158

1

ItemReaderAdapter 종료

0

87

1

[ 강좌 Git 브랜치 문의 ] 섹션 9 > JdbcCursorItemReader, JpaCursorItemReader

0

191

2

Spring Batch 배포 질문

0

255

2

spring batch 버전

0

239

2

retry count 관련 질문

0

185

2

StepExecutionListener 의 afterStep 에서 return ExitStatus.FAILED 에 의한 동작에 의문이 갑니다.

0

346

2

jdbc, jpa 커서방식 조회 방식 차이 질문 (강사님께 답변 받고 싶습니다)

0

242

2

Multithread step과 AsyncItemProcessor

0

208

2

job 재실행

0

259

2

bean 생명주기 문제 도와주세요(@Scope("step"), @Autowired)

0

192

1

Multi-threaded-step과 Partitioning 차이 확인

0

187

2

jdbcCursorReader, jdbcPagingReader 질문

0

149

1

step muti-thread 질문

0

114

1

itemSteam open update close 질문

0

120

1