Home > Mobile >  Spring Batch - delete
Spring Batch - delete

Time:11-15

How can I do the deletion of the entities that I just persisted?

@Bean
  public Job job() {
    return this.jobBuilderFactory.get("job")
        .start(this.syncStep())
        .build();
  }

  @Bean
  public Step syncStep() {
    // read
    RepositoryItemReader<Element1> reader = new RepositoryItemReader<>();
    reader.setRepository(repository);
    reader.setMethodName("findElements");
    reader.setArguments(new ArrayList<>(Arrays.asList(ZonedDateTime.now())));
    final HashMap<String, Sort.Direction> sorts = new HashMap<>();
    sorts.put("uid", Sort.Direction.ASC);
    reader.setSort(sorts);
    // write
    RepositoryItemWriter<Element1> writer = new RepositoryItemWriter<>();
    writer.setRepository(otherrepository);
    writer.setMethodName("save");
    return stepBuilderFactory.get("syncStep")
            .<Element1, Element2> chunk(10)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .build();
  }

It is a process of dumping elements. We pass the elements from one table to another.

CodePudding user response:

It is a process of dumping elements. We pass the elements from one table to another.

You can do that in two steps. The first step copies items from one table to another. The second step deletes the items from the source table. The second step should be executed only if the first step succeeds.

CodePudding user response:

There are a few options:

Using a CompositeItemWriter

You could create a second ItemWriter that does the delete logic, for example:

RepositoryItemWriter<Element1> deleteWriter = new RepositoryItemWriter<>();
deleteWriter.setRepository(repository);
deleteWriter.setMethodName("delete");

To execute both writers you can use a CompositeItemWriter:

CompositeItemWriter<User> writer = new CompositeItemWriter<>();
// 'saveWriter' would be the writer you currently have
writer.setDelegates(List.of(saveWriter, deleteWriter));

This however won't work if your ItemProcessor transforms the original entity to something completely new. In that case I suggest using PropertyExtractingDelegatingItemWriter.

(Note, according to this question the writers run sequentially and the second writer should not be executed if the first one fails, but I'm not 100% sure on that.)


Using a separate Step

Alternatively, you could put the new writer in an entirely separate Step:

@Bean
  public Step cleanupStep() {
    // Same reader as before (might want to put this in a separate @Bean)
    RepositoryItemReader<Element1> reader = new RepositoryItemReader<>();
    // ...
    // The 'deleteWriter' from before
    RepositoryItemWriter<Element1> deleteWriter = new RepositoryItemWriter<>();
    // ...
    return stepBuilderFactory.get("cleanupStep")
        .<Element1, Element2> chunk(10)
        .reader(reader)
        .writer(writer)
        .build();
  }

Now you can schedule the two steps individually:

@Bean
public Job job() {
    return this.jobBuilderFactory.get("job")
        .start(this.syncStep())
        .next(this.cleanupStep())
        .build();
}

Using a Tasklet

If you're using a separate step and depending on the amount of data, it might be more interesting to offload it entirely to the database and execute a single delete ... where ... query.

public class CleanupRepositoryTasklet implements Tasklet {
    private final Repository repository;

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        repository.customDeleteMethod();
        return RepeatStatus.FINISHED;
    }
}

This Tasklet can then be registered in the same way as before, by declaring a new Step in your configuration:

return this.stepBuilderFactory.get("cleanupStep")
    .tasklet(myTasklet())
    .build();
  • Related