인프런 커뮤니티 질문&답변

코린코린님의 프로필 이미지
코린코린

작성한 질문수

스프링 배치

DB - JdbcPagingItemReader

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

작성

·

340

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값만 짤려서 올라옵니다.

답변 1

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();
}
}

 

코린코린님의 프로필 이미지
코린코린

작성한 질문수

질문하기