1

I have a Spring batch application written on top of spring boot framework, it is used to read data from oracle database(using JDBCcursorItemreader) and write to Mongo Database(MongoItemWriter).For each table i'm having a POJO class .Null value field not displaying in mongo collection.By default searilaization omitting the null value columns are omitting and displaying only the non null columns.

is there any other property to include the null fields in mongo DB?

ex: Oracle table

enter image description here

Mongo Collection:

{
"Name":"xyz",
"Number":"16"
}

Want below format:

{
"Name":"xyz",
"Number":"16",
"Date" : null
}

I want to display the date column in mongo DB.I have tried with jsoninclude properties.it is not working. Can anyone suggest on this?

My Code: Batch File:

package com.sam.oracletomongo;

import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor;
import org.springframework.batch.core.job.builder.FlowBuilder;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.core.job.flow.support.SimpleFlow;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
import org.springframework.batch.item.data.MongoItemWriter;
import org.springframework.batch.item.data.builder.MongoItemWriterBuilder;
import org.springframework.batch.item.database.JdbcCursorItemReader;
import org.springframework.batch.item.database.builder.JdbcCursorItemReaderBuilder;
import org.springframework.batch.item.database.support.ListPreparedStatementSetter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.mongodb.core.MongoTemplate;

@Configuration
@EnableBatchProcessing
@Import(AdditionalBatchConfiguration.class)
public class BABatchConfig  {
    @Autowired
    public DataSource datasource;
    @Autowired
    public MongoTemplate mongotemplate;     
    
     @Autowired
        public JobBuilderFactory jobBuilderFactory;
        @Autowired
        public StepBuilderFactory stepBuilderFactory;
        @Bean
        @StepScope
        public JdbcCursorItemReader<BA> itemReaderBA(@Value("#{jobParameters[deltadate]}") String deltadate,@Value("#{jobParameters[rundate]}") String rundate) {
            ListPreparedStatementSetter listPreparedStatementSetter = new ListPreparedStatementSetter();    
            List<String> l1=new ArrayList<String>();
            l1.add(deltadate);
            l1.add(rundate);
            listPreparedStatementSetter.setParameters(l1);
            return new JdbcCursorItemReaderBuilder<BA>()
                .dataSource(datasource) // change accordingly if you use another data source
                .name("fooReader")
                .sql("SELECT SA_NO,SA_NAME,DATE1,DATE2,DATE3,ACTIVE FROM SAMPLE WHERE DATE2 between TO_DATE(?,'YYYY-MM-DD') and TO_DATE(?, 'YYYY-MM-DD')")
                .rowMapper(new BARowMapper())
                .preparedStatementSetter(listPreparedStatementSetter)
                .build();
        }               
        @Bean
        public MongoItemWriter<BA> writerBA(MongoTemplate mongoTemplate) {
            
            
            return new MongoItemWriterBuilder<BA>().template(mongoTemplate).collection("BA")
                    .build();
        }

       
    
        @Bean
public Job BAJob() {
            
            return jobBuilderFactory.get("BA")
                    .incrementer(new CustomParametersIncrementerImpl(datasource))
                    .start(BAstep())    
                    .build();
        }
        
        @Bean
        public Step BAstep() {
            return stepBuilderFactory.get("BAStep1")
                    .<BA, BA> chunk(10)
                    .reader(itemReaderBA(null,null))                    
                    .writer(writerBA(mongotemplate))

                    .build();
        }
       

            
      
}

Model Class:




package com.sam.oracletomongo;

public class BA {

private String _id;
private String saNo;
private String saName;
private String Date1;
private String Date2;
private String Date3;
private String active;

public String get_id() {
    return _id;
}
public void set_id(String _id) {
    this._id = _id;
}
public String getsaNo() {
    return saNo;
}
public void setBaNo(String saNo) {
    this.saNo = saNo;
}
public String getsaName() {
    return saName;
}
public void setBaName(String saName) {
    this.saName = saName;
}
public String getDate1() {
    return Date1;
}
public void setDate1(String Date1) {
    this.Date1 = Date1;
}
public String getDate2() {
    return Date2;
}
public void setDate2(String Date2) {
    this.Date2 = Date2;
}
public String getDate3() {
    return Date3;
}
public void setDate3(String Date3) {
    this.Date3 = Date3;
}
public String getActive() {
    return active;
}
public void setActive(String active) {
    this.active = active;
}
@Override
public String toString() {
    return "BA [_id=" + _id + ", saNo=" + saNo + ", saName=" + saName + ", Date1=" + Date1 + ", Date2="
            + Date2 + ", Date3=" + Date3 + ", active=" + active + "]";
}

}

Mapper Class:

package com.sam.oracletomongo;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

public class BARowMapper implements RowMapper<BA> {  
         
    public BA mapRow(ResultSet rs, int rowNum) throws SQLException 
    {  
            BA ba = new BA();
            String id=rs.getString("sA_NO");
            ba.set_id(id); 
            ba.setsaNo(rs.getString("sA_NO"));
            ba.setsaName(rs.getString("sA_NAME"));
            ba.setDate1(rs.getString("DATE1"));
            ba.setDate2(rs.getString("DATE2"));
            ba.setDate3(rs.getString("DATE3"));
            ba.setActive(rs.getString("ACTIVE"));
            return ba;  
    }  
        
}
Murat Colyaran
  • 2,075
  • 2
  • 8
  • 27
Ayesha
  • 37
  • 1
  • 11
  • Use `$project` Pipeline stage of aggregation and use `$isNull` for the key you want to project as null for non-existsnce of the key you are looking for. Let me know if you a sample code – hhharsha36 Jun 23 '21 at 13:21
  • Does this answer your question? [Spring Data mongo to insert null values to DB](https://stackoverflow.com/questions/41112607/spring-data-mongo-to-insert-null-values-to-db) – Mahmoud Ben Hassine Jun 24 '21 at 07:52

1 Answers1

0

This $project stage can help you:

  {
    "$project": {
      _id: 0,
      "name": 1,
      "number": 1,
      "Date": {
        "$ifNull": [
          "$Date", //If the Date field is not null
          "null" //If the Date field is null write string 'null' to the field
        ]
      }
    }
  }
Murat Colyaran
  • 2,075
  • 2
  • 8
  • 27
  • I'm not sure where to use the above snippet and my POJO class converting to document automatically during the mongoitemwriter writes the data into MongoDB. Please suggest based on my code. – Ayesha Jun 23 '21 at 13:44
  • I'm not sure either, I never worked with Pojo before but there is definitely a system where aggregation stages can be written. If you adapt this stage there, it will work. – Murat Colyaran Jun 23 '21 at 13:46