2017-09-20 1 views
1

스프링 데이터 JPA와 스프링 배치와 함께 스프링 부트 1.5.7을 사용하고 있습니다. 엔티티를 읽으려면 JpaPagingItemReader<T>을 사용하고 엔티티를 읽으려면 JpaItemWriter<T>을 사용합니다. 내가하고 싶은 것은 특정 데이터베이스 테이블에서 데이터를 읽은 다음 다른 형식으로 변환하고 다른 테이블에 다시 쓰는 것입니다. 원시 json 문자열을 읽고 deserialize하고 특정 테이블에 삽입합니다.상태 변경을 통한 스프링 일괄 쿼리

나는 처리 한 후에 읽은 데이터를 삭제할 계획이 아니라 처리 된 것으로 표시하려고합니다. 그것에 어떤 포인터가없는 경우

@Bean 
    public ItemReader<RdJsonStore> reader(){ 
     JpaPagingItemReader<RdJsonStore> reader = new JpaPagingItemReader<>(); 
     reader.setEntityManagerFactory(entityManagerFactory); 
     reader.setQueryString("select e from RdJsonStore e "+ 
           "where e.jsonStoreProcessedPointer is null"); 
     reader.setPageSize(rawDataProperties.getBatchProcessingSize()); 
     return reader; 
    } 

은 그래서 읽기 전용 것 : 문제는 내가 이런 일에 질의를 한 경우 JpaPagingItemReader 핸들이 잘 읽는 것입니다. 나는 항목을 처리 한 후에 포인터를 삽입 할 것입니다 (일괄 처리에서는 1000 개의 항목을 처리하고 모든 ID를 포인터 테이블에 게시하는 것처럼).

이렇게 실행될 때 반환되는 데이터를 변경하면 ItemWriter (및 JPA 하나)가 데이터를 처리 할 수 ​​있습니까 (쿼리 할 항목은 모든 배치와 함께 축소됩니다)?

포인터 솔루션을 적용 할 수없는 경우 DB 대 DB 일괄 처리 작업을 어떻게 설계해야합니까?

내 소스 테이블은 다음과 같습니다

당신이 방법 doReadPage()를 들어, JpaPagingItemReader의 코드를 보면

enter image description here

+0

아니, 기본 데이터가 변경되고 각 페이지에 대해 쿼리가 다시 실행되면 데이터가 손실되기 시작합니다. –

+0

@ M.Deinum 그게 내가 생각한 바예요. ( – appl3r

답변

0

,이 라인을 알 수 있습니다,

Query query = createQuery().setFirstResult(getPage() * getPageSize()).setMaxResults(getPageSize());

createQuery()을 그대로,

private Query createQuery() { 
     if (queryProvider == null) { 
      return entityManager.createQuery(queryString); 
     } 
     else { 
      return queryProvider.createQuery(); 
     } 
    } 

각 페이지마다 새로 작성/실행되지만 새 데이터 세트마다 페이지 번호가 다시 계산되지 않으며 페이지 번호 재 계산도 이해가되지 않습니다.

getPageSize()는 항상 값은 구성 및 getPage() 반환에 설정 마지막으로 계산 된 페이지 번호 (이전에 처리 된 페이지 + 1) 그래서 데이터가 축소되는 경우 페이지 번호 계산은 또한 당신은 항상 페이지로 시작 새롭게 예를 수행하는 경우, 프로그램이 제대로 작동 반환 = 0이고 JpaPagingItemReader과 함께 발생하지 않으므로 M Deinum에서 지정한대로 데이터가 누락됩니다.

또한 새로운 데이터 추가는 정상적으로 작동합니다. (작업 실행 중에 보통이 잠겨 있다고하더라도 데이터 잠김으로 정렬 키가 있으면 새 레코드가 끝에 추가됩니다).

현재 작업 실행 중에 행을 PROCESSED으로 표시하는 것은 프레임 워크가 이미 처리 했으므로 아무런 도움이되지 않습니다 (레코드가 두 번 처리되지 않음).

당신이 실행다음 작업을 위해 처리 등의 기록을 마킹해야 할 수도 있습니다 그리고 그 끝에 다음 (작업 실행 중) WHERE 조항의 일부가 아닌 별도의 플래그를 업데이트하여 처리 할 수 ​​있습니다 작업 - WHERE 절 (처리 된 레코드를 나타 내기 위해 WHERE 절에서 사용하는)의 일부인 플래그를 업데이트하십시오.

+0

사용자가 수동으로 작업을 시작하기 때문에 표시하고 싶었습니다. 그리고 같은 리소스로 Job을 다시 시작하면 데이터를 복제 할 수 있습니다. 내가 읽을 때가 아니라 쓸 때 이것을 처리하십시오. – appl3r

관련 문제