2017-08-08 1 views
1

J'ai un projet de lot de printemps existant qui lit des données de MySQL ou ArangoDB (base de données NoSql) basé sur la décision de basculement de fonctionnalité au démarrage et fait un peu de traitement et réécrit à MySQL/ArangoDB.Printemps Lots multiples lecteurs pour différents DB

Maintenant, la configuration du lecteur pour MySQL est quelque chose comme ci-dessous,

@Bean 
@Primary 
@StepScope 
public HibernatePagingItemReader reader(
     @Value("#{jobParameters[oldMetadataDefinitionId]}") Long oldMetadataDefinitionId) { 

    Map<String, Object> queryParameters = new HashMap<>(); 
    queryParameters.put(Constants.OLD_METADATA_DEFINITION_ID, oldMetadataDefinitionId); 


    HibernatePagingItemReader<Long> reader = new HibernatePagingItemReader<>(); 

    reader.setUseStatelessSession(false); 
    reader.setPageSize(250); 
    reader.setParameterValues(queryParameters); 

    reader.setSessionFactory(((HibernateEntityManagerFactory) entityManagerFactory.getObject()).getSessionFactory()); 
    return reader; 
} 

et j'ai un autre lecteur de Arango comme ci-dessous,

@Bean 
@StepScope 
public ListItemReader arangoReader(
     @Value("#{jobParameters[oldMetadataDefinitionId]}") Long oldMetadataDefinitionId) { 

    List<InstanceDTO> instanceList = new ArrayList<InstanceDTO>(); 

    PersistenceService arangoPersistence = arangoConfiguration 
      .getPersistenceService()); 

    List<Long> instanceIds = arangoPersistence.getDefinitionInstanceIds(oldMetadataDefinitionId); 

    instanceIds.forEach((instanceId) -> 
    { 
     InstanceDTO instanceDto = new InstanceDTO(); 
     instanceDto.setDefinitionID(oldMetadataDefinitionId); 
     instanceDto.setInstanceID(instanceId); 
     instanceList.add(instanceDto); 

    }); 

    return new ListItemReader(instanceList); 

} 

et ma configuration étape est inférieure,

@Bean 
@SuppressWarnings("unchecked") 
public Step InstanceMergeStep(ListItemReader arangoReader, ItemWriter<MetadataInstanceDTO> arangoWriter, 
     ItemReader<Long> mysqlReader, ItemWriter<Long> mysqlWriter) { 

    Step step = null; 
    if (arangoUsage) { 
     step = steps.get("arangoInstanceMergeStep") 


       .<Long, Long>chunk(1) 

       .reader(arangoReader) 

       .writer(arangoWriter) 


       .faultTolerant() 


       .skip(Exception.class) 


       .skipLimit(10) 

       .taskExecutor(stepTaskExecutor()) 

       .build(); 


     ((TaskletStep) step).registerChunkListener(chunkListener); 
    } 
    else { 
     step = steps.get("mysqlInstanceMergeStep") 


       .<Long, Long>chunk(1) 

       .reader(mysqlReader) 

       .writer(mysqlWriter) 

       .faultTolerant() 

       .skip(Exception.class) 


       .skipLimit(failedSkipLimit) 

       .taskExecutor(stepTaskExecutor()) 

       .build(); 


     ((TaskletStep) step).registerChunkListener(chunkListener); 

    } 

    return step; 
} 

Le lecteur MySQL prend en charge la pagination via HibernatePagingItemReader afin qu'il soit géré e millions d'articles sans aucun problème de mémoire.

Je veux implémenter le même support de pagination pour qu'arango reader ne récupère que 250 documents par itération comment modifier le code du lecteur d'arango pour y arriver?

Répondre

0

Tout d'abord la documentation de ListItemReader dit que - Utile pour tester donc ne l'utilisez pas pour la production. Renvoyer un ItemReader à la place de tous vos lecteurs de haricots au lieu de types concrets réels. Cela dit, Spring Batch API ou Spring Data ne semble pas supporter Arango DB. Le plus proche que j'ai pu trouver est this

(je n'ai pas travaillé avec Arango DB auparavant).

Donc, à mon avis, vous devez écrire votre propre lecteur de Arango personnalisé qui implémente la pagination en peut-être mise en œuvre de classe abstraite - org.springframework.batch.item.database.AbstractPagingItemReader

Si ce ne est pas faisable en étendant au-dessus de classe, vous pourriez avoir à tout mettre en œuvre à partir de zéro. Tous les lecteurs de pagination de Spring Batch API étendent cette classe abstraite, y compris HibernatePagingItemReader.

Aussi, rappelez-vous que jeu d'enregistrements de Arango devrait avoir une sorte de commande pour mettre en œuvre la pagination afin que nous puissions établir une distinction entre la page - 0 & Page -1 etc (similaire à ORDER BY clause, BETWEEN opérateur & moins, plus que les opérateurs, etc en SQL aussi FETCH FIRST XXX ROWS ou LIMIT clause type de chose serait nécessaire aussi).

La mise en œuvre par vos soins n'est pas une tâche très difficile car vous devez calculer le nombre total d'éléments possibles, les trier, puis les diviser en pages et ne récupérer qu'une seule page à la fois.

Regardez API pour des implémentations comme - HibernatePagingItemReader etc pour avoir des idées.

Espérons que ça aide !!

+0

Merci @sabir pour la clarification ci-dessus !! , sera-t-il possible d'appeler le lecteur plusieurs fois de arangoMergeStep avec startIndex dynamique et endIndex pour récupérer seulement des enregistrements limités pour les requêtes AQL en utilisant spring boot. – siva

+0

C'est la méthode 'read()' du lecteur qui sera appelée plusieurs fois par framework. Cette méthode 'read()' devrait continuer à renvoyer un à un les éléments jusqu'à ce qu'une page soit terminée, puis récupérer la page suivante. vous renvoyez "null" pour le dernier élément de la dernière page.Regardez l'une des classes existantes comme - 'JdbcPagingItemReader' ou' HibernatePagingItemReader' etc. Le travail de votre lecteur personnalisé sera de maintenir ces éléments et comptes puisque le contrat est de renvoyer un seul élément chaque fois qu'une lecture est appelée. –