我的数据是这样的
UserId,UserData

1,data11

1,data12

2,data21

3,data31

问题是我如何使Spring Batch ItemReader读取多行并映射到像

Map < userid, List < userdata > >


谢谢。

最佳答案

遵循的步骤:


通过实现ItemWriter创建自定义Item Writer类,其中我们实现了将User对象存储在Map<String,List<String>>中的逻辑,因为单个用户可以拥有多个关联数据

package com.spring.batch.domain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.batch.item.ItemWriter;

public class UserItemWriter implements ItemWriter<User> {

    private static Map<String, List<String>> userMap = new HashMap<String, List<String>>();

    public void write(List<? extends User> users) throws Exception {

        for (User user : users) {
            List<String> list = userMap.get(user.getUserId());
            if (list == null) {
                list = new ArrayList<String>();
            }
            list.add(user.getUserData());
            userMap.put(user.getUserId(), list);
        }
    }

    public static Map<String, List<String>> getUserMap() {
        return userMap;
    }

}

具有两个字段UseruserId的普通userData POJO类

package com.spring.batch.domain;

public class User {
    private String userId;
    private String userData;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserData() {
        return userData;
    }

    public void setUserData(String userData) {
        this.userData = userData;
    }

}

主班办事

package com.spring.batch.main;

import java.util.List;
import java.util.Map;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.batch.domain.UserItemWriter;

public class Main {
    public static void main(String[] args) throws BeansException,
            JobExecutionAlreadyRunningException, JobRestartException,
            JobInstanceAlreadyCompleteException, JobParametersInvalidException {
        ApplicationContext appContext = new ClassPathXmlApplicationContext(
                "config/application-context.xml");
        JobLauncher jobLauncher = (JobLauncher) appContext.getBean("jobLauncher");
        jobLauncher.run(
                (Job) appContext.getBean("job"),
                new JobParametersBuilder().addString("input.file.name",
                        "file:src/main/resources/data/input.csv").toJobParameters());

        Map<String,List<String>> userMap=UserItemWriter.getUserMap();
        for (String userId : userMap.keySet()) {
            System.out.println(userId + ":" + userMap.get(userId));
        }
    }
}

application-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

    <import resource="jobs.xml" />

    <bean id="jobLauncher"
        class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <property name="jobRepository" ref="jobRepository" />
    </bean>

    <bean id="jobRepository"
        class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
        <property name="transactionManager" ref="transactionManager" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

</beans>

jobs.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

    <job id="job" restartable="false"
        xmlns="http://www.springframework.org/schema/batch">
        <step id="step1">
            <tasklet>
                <chunk reader="csvItemReader" writer="userItemWriter"
                    commit-interval="2">
                </chunk>
            </tasklet>
        </step>
    </job>

    <bean id="userItemWriter" class="com.spring.batch.domain.UserItemWriter"
        scope="step" />

    <bean id="csvItemReader" class="org.springframework.batch.item.file.FlatFileItemReader"
        scope="step">
        <property name="lineMapper">
            <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <property name="lineTokenizer">
                    <bean
                        class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                        <property name="names" value="userId,userData" />
                    </bean>
                </property>
                <property name="fieldSetMapper">
                    <bean
                        class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
                        <property name="prototypeBeanName" value="user" />
                    </bean>
                </property>
            </bean>
        </property>
        <property name="linesToSkip" value="1" />
        <property name="resource" value="#{jobParameters['input.file.name']}" />
    </bean>

    <bean id="user" class="com.spring.batch.domain.User" scope="prototype" />

</beans>

input.csv

UserId,UserData
1,data11
1,data12
2,data21
3,data31

项目结构屏幕截图(Maven)

09-10 10:17
查看更多