spring-batchjparepository

SpringBatch ItemRepositoryReader, How to change datasources in a JPARepository?


I am working with SpringBatch and JPARepository. I have 2 Connections DB2 & Postgres. I need to switch the DataSources inside a JpaRepository

So, to hold the DataSource Context, I followed the link : [AbstractRoutingDataSource][1] So here below is the code

public class ClientDatabaseContextHolder {

    private static ThreadLocal<ClientDatabase> CONTEXT
      = new ThreadLocal<>();

    public static void set(ClientDatabase clientDatabase) {
        Assert.notNull(clientDatabase, "clientDatabase cannot be null");
        CONTEXT.set(clientDatabase);
    }

    public static ClientDatabase getClientDatabase() {
        return CONTEXT.get();
    }

    public static void clear() {
        CONTEXT.remove();
    }
}

Then, In my RepositoryItemReader I want to set to My 1st DataSource Client

@Component
public class ClientReader extends RepositoryItemReader<Client>  {
    public ClientReader(final ClientModelsRepository clientRepository) {
        DataSourceContextHolder.set("client"); // <===== SET HERE MY 1st Datasource
        this.setRepository(clientRepository);
        this.setMethodName("findAllWithFriends");
        this.setSort(new HashMap<>());
        this.setPageSize(5000);
    }
}

Then In my JPARepository, I would like to change the DataSource to the 2nd.

 @Transactional(Transactional.TxType.NOT_SUPPORTED)
    default Page<Client> findAllWithFriends(final Pageable pageable) {

        final Page<Client> clients = this.findAll(pageable);
     

        if (clients.hasContent()) {          

            DataSourceContextHolder.set("friends"); // <== I WANT TO CHANGE THE DATASOURCE THERE

             final List<Friend> friends = AppContext.getBean(FriendRepository.class).findByClientCodeIn(clientStringList);    
             clients.getContent().forEach(c -> {   c.setFriends(friends); });   

        }
        return clients;
    }

My question is how to change of datasource when reading a chunck. I dont think it is possible to set 2 different datasources and methods in the ClientReader. I have also tried to set the 2nd datasource inside the FriendRepository.class but it doesn't work too. I don't want to do it in the Processor because I want to get all friends matching for the 5000 Client codes. Do you have any ideas ? [1]: https://www.baeldung.com/spring-abstract-routing-data-source


Solution

  • we finally found that :

    @Transactional(Transactional.TxType.REQUIRES_NEW) List findByClientCodeIn(List codes);

    REQUIRES_NEW creates new transactions every time the method is called