Table of Contents
JpaPagingItemReader
페이징 방식에는 두가지 문제가 있다.
-
페이지가 무지 커지게 되면 성능문제가 발생한다.
-
어디까지 가져왔는지 표시하면서 데이타를 가져오게 되면 가져오지 못하는 데이타가 발생한다.
SELECT e
FROM SrcItemEntity e JOIN SrcItemTransferEntity t ON e.id = t.itemid
WHERE t.transferDate <= e.modifiedAt
ORDER BY e.id
위와같은 쿼리로 데이타를 가져오고,
transferDate 를 수정하게 되면,
처음 1~10개 가져온 후 transferDate 를 수정하게 되면
다음 2번째 페이지를 가져올때
11~20이 아니라 21~30 을 가져오게 된다.
이 문제를 해결하기 위해 getPage() 를 수정해서,
항상 첫번째 페이지만 가져오도록 수정할 수 있다.
@Slf4j
@Configuration
public class SrcItemReader {
private final EntityManagerFactory entityManagerFactory;
public SrcItemReader(@Qualifier("ServerEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
@Value("${batch.read-product.size}")
private int readProduct;
@Bean
public JpaPagingItemReader<SrcItemEntity> readForUpdate() {
JpaPagingItemReader<SrcItemEntity> reader = new JpaPagingItemReader<>() {
@Override
public int getPage() {
return 0;
}
};
try {
reader.setQueryString(
" SELECT e "
+ " FROM SrcItemEntity e JOIN SrcItemTransferEntity t ON e.id = t.itemid "
+ " WHERE t.transferDate <= e.modifiedAt "
+ " ORDER BY e.id "
);
reader.setPageSize(readProduct);
reader.setName("readForUpdate");
reader.setEntityManagerFactory(entityManagerFactory);
} catch (Exception e) {
throw new RuntimeException("Unknown exception occurred", e);
}
return reader;
}
@Bean
public JpaPagingItemReader<SrcItemEntity> readForInsert() {
JpaPagingItemReader<SrcItemEntity> reader = new JpaPagingItemReader<>() {
@Override
public int getPage() {
return 0;
}
};
try {
reader.setQueryString(
" SELECT e "
+ " FROM SrcItemEntity e LEFT JOIN SrcItemTransferEntity t ON e.id = t.itemid "
+ " WHERE t.itemid is NULL "
+ " ORDER BY e.id "
);
reader.setPageSize(readProduct);
reader.setName("readForInsert");
reader.setEntityManagerFactory(entityManagerFactory);
} catch (Exception e) {
throw new RuntimeException("Unknown exception occurred", e);
}
return reader;
}
}