Roberto
Roberto

Reputation: 1395

How to create spring-batch ItemWriter for entity with ArrayList field?

I user spring-batch to locate entity by tables. Question is about ItemWriter or, may be, about ItemProcessor.

For this entity everything okey. I can read entity from source and save it table User_export

@Getter @Setter
class User{
    String objectId;
    String rev;
    String value;
    String type;
}

And I had this ItemWriter:

    @Bean
    @StepScope
    public ItemWriter<UserExport> writer() {
        JdbcBatchItemWriter<UserExport> writer = new JdbcBatchItemWriter<>();
        writer.setDataSource(dataSource);

        String sql = "insert into User_export(objectId, REV, Value, Type)" +
                "values (:objectId, :rev, :value, :type)";
        writer.setSql(sql);

        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
        writer.afterPropertiesSet();
        return writer;
    }

2) Than, I added field in my entity User. This field is list and I need to save this field in other table - Device_Export.

@Getter @Setter
class User{
    String objectId;
    String rev;
    String value;
    String type;
    List<String> devices;
}

I have two tables User_export and Device_export. Device_export has foreign key to User_export and relation is many devices to one user. I need to map my user-entity by tables. So, my solution is:

     @Bean
    public Step exportStep1() {
        return stepBuilderFactory.get("step1").<InputUser, List<OutputUser>>chunk(1)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .build();
    }

reader->processor->writer

Reader (read entity from source talbe) - this is okey.

@Bean
public JdbcCursorItemReader<User> reader() {
    JdbcCursorItemReader<InputUser> reader = new JdbcCursorItemReader<>();
    String sql = "select * from User_Table";
    reader.setSql(sql);
    reader.setDataSource(dataSource);
    reader.setName("User_Table");
    reader.setRowMapper(new BeanPropertyRowMapper<>(User.class));
    return reader;
}

After processing, I have User entity with filled list of devices. I need to map it to tables:

I used ComposeWriter:

@Bean
    @StepScope
    @DependsOn({"userWriter", "deviceWriter"})
    public CompositeItemWriter composeWriter() {
        CompositeItemWriter writer = new CompositeItemWriter();

        ItemWriter<UserExport> userWriter = userWriter();
        ItemWriter<DeviceExport> deviceWriter = deviceWriter();
        List<ItemWriter> writers = new ArrayList<>();
        writers.add(userWriter);
        writers.add(deviceWriter);

        writer.setDelegates(writers);
        return writer;
    }


    @Bean
    @StepScope
    public ItemWriter<UserExport> userWriter() {
        JdbcBatchItemWriter<UserExport> writer = new JdbcBatchItemWriter<>();
        writer.setDataSource(dataSource);

        String sql = "insert into User_Export (objectId, REV, Value, Type)" 
                "values (:objectId, :rev, :value, :type)";
        writer.setSql(sql);

        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
        writer.afterPropertiesSet();
        return writer;
    }

    @Bean
    @StepScope
    public ItemWriter<DeviceExport> deviceWriter() {
        JdbcBatchItemWriter<DeviceExport> writer = new JdbcBatchItemWriter<>();
        writer.setDataSource(dataSource);

        String sql = "insert into Device_Export (PR_KEY, objectId, device) values (:prKey, :objectId, :device)";
        writer.setSql(sql);

        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
        writer.afterPropertiesSet();
        return writer;
    }

But with ItemWriter like this, I can just write only one record in devices table. How to write list of devices(records) in Device_export?

My approximately processor like this:

    @Bean
    public ItemProcessor<User, List<OutputUser>> processor() {
        return new ItemProcessor<User, List<OutputUser>>() {
            @Override
            public List<OutputUser> process(OutputUser item) throws Exception {
                OutputUser outputUser = mapToUser(item);
                List<OutputDevice> outputDevices = mapToDevices(item);
                // Не понятно что делать дальше
            }
        };
    }

Upvotes: 4

Views: 2951

Answers (1)

Mahmoud Ben Hassine
Mahmoud Ben Hassine

Reputation: 31720

The JdbcBatchItemWriter won't help. You need to write the code to save a user with its devices and wrap that code is a custom Spring Batch writer. Otherwise use an ORM to map your entities to tables and use the JpaItemWriter or HibernateItemWriter.

A similar question here: Read one record/item and write multiple records/items using spring batch

Upvotes: 1

Related Questions