0

Im new to spring framework and I Want to migrate data from One DB to another using Spring boot n Batch

Im trying to read from an Mysql db with an item reader and write it to an Oracle db using an item writer of the same job.

Im able to read the data from the Mysql db but unable to write it to Oracle Db as the writer is trying it write it in Mysql Db itself.

Im not sure why the connection is not switching to Oracle db.

Please help me over here what im doing wrong.

Application properties

server.port=8082

spring.batch.job.enabled= false

spring.datasource.url = jdbc:mysql://localhost:3306/projectdb1
spring.datasource.username = root
spring.datasource.password = Mech_2015
spring.datasource.driverClassName = com.mysql.jdbc.Driver


#second db2 ...
db2.datasource.url = jdbc:oracle:thin:@localhost:1521:xe 
db2.datasource.username = system
db2.datasource.password = Mech_2015
db2.datasource.driverClassName = oracle.jdbc.driver.OracleDriver

Entity Managers

package com.techprimers.springbatchexample1.entity.manger;
@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "radiusEntityManager", transactionManagerRef = "radiusTransactionManager", basePackages = "com.techprimers.springbatchexample1.repository.userrepo")
public class RadiusConfig {

    private final PersistenceUnitManager persistenceUnitManager;

    public RadiusConfig(ObjectProvider<PersistenceUnitManager> persistenceUnitManager) {
        this.persistenceUnitManager = persistenceUnitManager.getIfAvailable();
    }

    @Bean
    @ConfigurationProperties("spring.jpa")
    public JpaProperties radiusJpaProperties() {
        return new JpaProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource")
    public DataSourceProperties radiusDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.properties")
    public DataSource radiusDataSource() {
        return (DataSource) radiusDataSourceProperties().initializeDataSourceBuilder().type(DataSource.class).build();
    }

    @Bean(name = "radiusEntityManager")
    public LocalContainerEntityManagerFactoryBean radiusEntityManager(JpaProperties radiusJpaProperties) {
        EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(radiusJpaProperties);
        return builder.dataSource(radiusDataSource()).packages(User.class).persistenceUnit("userDs").build();
    }

    @Bean
    public JpaTransactionManager radiusTransactionManager(EntityManagerFactory radiusEntityManager) {
        return new JpaTransactionManager(radiusEntityManager);
    }

    private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties radiusJpaProperties) {
        JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(radiusJpaProperties);
        return new EntityManagerFactoryBuilder(jpaVendorAdapter, radiusJpaProperties.getProperties(),
                this.persistenceUnitManager);
    }

    private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(jpaProperties.isShowSql());
        adapter.setDatabase(jpaProperties.getDatabase());
        adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
        adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
        return adapter;
    }

}

package com.techprimers.springbatchexample1.entity.manger;

@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "esbEntityManager", transactionManagerRef = "esbDetailsTransactionManager", basePackages = "com.techprimers.springbatchexample1.repository.userdetails")
public class EsbConfig {

    private final PersistenceUnitManager persistenceUnitManager;

    public EsbConfig(ObjectProvider<PersistenceUnitManager> persistenceUnitManager) {
        this.persistenceUnitManager = persistenceUnitManager.getIfAvailable();
    }

    @Bean
    @ConfigurationProperties("db2.jpa")
    public JpaProperties esbJpaProperties() {
        return new JpaProperties();
    }

    @Bean
    @ConfigurationProperties("db2.datasource")
    public DataSourceProperties esbDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties(prefix = "db2.datasource.properties")
    public DataSource esbDataSource() {
        return (DataSource) esbDataSourceProperties().initializeDataSourceBuilder().type(DataSource.class).build();
    }

    @Bean(name = "esbEntityManager")
    public LocalContainerEntityManagerFactoryBean esbEntityManager(JpaProperties esbJpaProperties) {
        EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(esbJpaProperties);
        return builder.dataSource(esbDataSource()).packages(UserDetails.class).persistenceUnit("userDetailDs").build();
    }

    @Bean
    public JpaTransactionManager esbTransactionManager(EntityManagerFactory esbEntityManager) {
        return new JpaTransactionManager(esbEntityManager);
    }

    private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties esbJpaProperties) {
        JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(esbJpaProperties);
        return new EntityManagerFactoryBuilder(jpaVendorAdapter, esbJpaProperties.getProperties(),
                this.persistenceUnitManager);
    }

    private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(jpaProperties.isShowSql());
        adapter.setDatabase(jpaProperties.getDatabase());
        adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
        adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
        return adapter;
    }

}

Batch Config

package com.techprimers.springbatchexample1.config;

@Configuration
@EnableBatchProcessing
public class SpringBatchConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(SpringBatchConfig.class);


    @Bean
    @Primary
    @Qualifier("radiusDatasource")
    @ConfigurationProperties(prefix = "spring.datasource")
    DataSource mysqlDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "db2.datasource")
    @Qualifier("esbDatasource")
    DataSource oracleDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public InspectionProcessor processor() {
        return new InspectionProcessor();
    }

    @Bean
    public JdbcCursorItemReader<User> reader() {
        JdbcCursorItemReader<User> cursorItemReader = new JdbcCursorItemReader<>();
        cursorItemReader.setDataSource(mysqlDataSource());
        cursorItemReader.setSql("SELECT ID,CNAME,SID,CREATEDDATE,COMPLETEDDATE FROM INSPECTION");
        cursorItemReader.setRowMapper(new InspectionDetailRowmapper());
        return cursorItemReader;
    }

    private static final String QUERY_INSERT_STUDENT = "INSERT "
            + "INTO inspect(id,cname,completeddate,createddate,lastupdateddate,sid) " + "VALUES (?,?,?,?,?,?)";

    @Bean
    ItemWriter<UserDetails> databaseItemWriter(DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate) {

        LOGGER.info("Starting writer");

        JdbcBatchItemWriter<UserDetails> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(oracleDataSource());
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);

        LOGGER.info(" writer");

        databaseItemWriter.setSql(QUERY_INSERT_STUDENT)

        ItemPreparedStatementSetter<UserDetails> valueSetter = new UserDetailsPreparedStatementSetter();
        databaseItemWriter.setItemPreparedStatementSetter(valueSetter);


        return databaseItemWriter;
    }

    @Bean
    Step dataMigrationStep(ItemReader<User> reader, ItemProcessor<User, UserDetails> processor,
            ItemWriter<UserDetails> databsaeItemWriter, StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory.get("dataMigrationStep").<User, UserDetails>chunk(5).reader(reader)
                .processor(processor).writer(databsaeItemWriter).build();
    }

    @Bean
    Job dataMigrationJob(JobBuilderFactory jobBuilderFactory, @Qualifier("dataMigrationStep") Step dataMigrationStep) {
        return jobBuilderFactory.get("csvFileToDatabaseJob").incrementer(new RunIdIncrementer()).flow(dataMigrationStep)
                .end().build();
    }

}

GoMohan
  • 11
  • 1
  • 3

1 Answers1

1

Your writer does not inject properly the database where to write your data

this

    @Bean
    ItemWriter<UserDetails> databaseItemWriter(DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate) 

instead of

    @Bean
    ItemWriter<UserDetails> databaseItemWriter(@Qualifier("esbDatasource") DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate) 
gaetan224
  • 586
  • 3
  • 13
  • I did try that qualifier annotation but I'm getting the below error – GoMohan Jun 30 '20 at 15:44
  • Error creating bean with name 'databaseItemWriter' defined in class path resource [com/techprimers/springbatchexample1/config/SpringBatchConfig.class]: Unsatisfied dependency expressed through method 'databaseItemWriter' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=esbDatasource)} – GoMohan Jun 30 '20 at 15:45
  • try naming your bean using @Bean(name="myBeanName") – gaetan224 Jun 30 '20 at 15:53
  • Since you annotated your mysql datasource with `@Primary`, it is the one injected in your writer. Adding a qualifier as in this answer should work. – Mahmoud Ben Hassine Jul 06 '20 at 11:15