Spring Batch 综合案例实战下

需求三:使用分区的方式将employee_temp表的数据读取并写入到employee表

步骤1:在com.langfeiyes.exp.job.config 包添加DBToDBJobConfig, 配置从数据库到数据库的作业

package com.langfeiyes.exp.job.config;


import com.langfeiyes.exp.domain.Employee;
import com.langfeiyes.exp.job.partitioner.DBToDBPartitioner;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.batch.MyBatisBatchItemWriter;
import org.mybatis.spring.batch.MyBatisPagingItemReader;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
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.launch.support.RunIdIncrementer;
import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
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.core.task.SimpleAsyncTaskExecutor;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 将数据从employee_temp中读取,并写入employe 表
 */
@Configuration
public class DBToDBJobConfig {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    public static int PAGESIZE = 1000;   //mybatis分页读取数据,跟chunkSize 一样
    public static int RANGE = 10000;  //每个分区读取数据范围(理解为个数)
    public static int GRIDSIZE = 50;  //分区个数


    //读数据-从employee_temp 表读 -- mybatis
    @Bean
    @StepScope
    public MyBatisPagingItemReader<Employee> dBToDBJobItemReader(
            @Value("#{stepExecutionContext[from]}") final Integer from,
            @Value("#{stepExecutionContext[to]}") final Integer to,
            @Value("#{stepExecutionContext[range]}") final Integer range){

        System.out.println("----------MyBatisPagingItemReader开始-----from: " + from + "  -----to:" + to + "  -----每片数量:" + range);
        MyBatisPagingItemReader<Employee> itemReader = new MyBatisPagingItemReader<Employee>();
        itemReader.setSqlSessionFactory(sqlSessionFactory);
        itemReader.setQueryId("com.langfeiyes.exp.mapper.EmployeeMapper.selectTempForList");
        itemReader.setPageSize(DBToDBJobConfig.PAGESIZE);
        Map<String, Object> map = new HashMap<>();
        map.put("from", from);
        map.put("to", to);
        itemReader.setParameterValues(map);

        return itemReader;
    }


    //数据库写- 写入到employee 表中
   @Bean
    public MyBatisBatchItemWriter<Employee> dbToDBItemWriter(){
        MyBatisBatchItemWriter<Employee> itemWriter = new MyBatisBatchItemWriter<>();
        itemWriter.setSqlSessionFactory(sqlSessionFactory);
        itemWriter.setStatementId("com.langfeiyes.exp.mapper.EmployeeMapper.save");  //操作sql
        return itemWriter;
    }

    //文件分区处理器-处理分区
    @Bean
    public PartitionHandler dbToDBPartitionHandler() {
        TaskExecutorPartitionHandler handler = new TaskExecutorPartitionHandler();
        handler.setGridSize(DBToDBJobConfig.GRIDSIZE);
        handler.setTaskExecutor(new SimpleAsyncTaskExecutor());
        handler.setStep(workStep());
        try {
            handler.afterPropertiesSet();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return handler;
    }

    //每个从分区操作步骤
    @Bean
    public Step workStep() {
        return stepBuilderFactory.get("workStep")
                .<Employee, Employee>chunk(DBToDBJobConfig.PAGESIZE)
                .reader(dBToDBJobItemReader(null, null, null))
                .writer(dbToDBItemWriter())
                .build();
    }

    @Bean
    public DBToDBPartitioner dbToDBPartitioner(){
        return new DBToDBPartitioner();
    }

    //主分区操作步骤
    @Bean
    public Step masterStep() {
        return stepBuilderFactory.get("masterStep")
                .partitioner(workStep().getName(),dbToDBPartitioner())
                .partitionHandler(dbToDBPartitionHandler())
                .build();
    }

    @Bean
    public Job dbToDBJob(){
        return jobBuilderFactory.get("dbToDB-step-job")
                .start(masterStep())
                .incrementer(new RunIdIncrementer())
                .build();
    }
}

步骤2:修改EmployeeMapper.xml

<select id="selectTempForList" resultMap="BaseResultMap">
    select * from employee_temp where id between #{from} and #{to}  limit #{_pagesize} OFFSET #{_skiprows}
</select>

步骤3:在com.langfeiyes.exp.job.partitioner 创建DBToDBPartitioner, 用于分区

package com.langfeiyes.exp.job.partitioner;

import com.langfeiyes.exp.job.config.DBToDBJobConfig;
import org.springframework.batch.core.partition.support.Partitioner;
import org.springframework.batch.item.ExecutionContext;

import java.util.HashMap;
import java.util.Map;

public class DBToDBPartitioner implements Partitioner {
    //约定分50个区, 每个区10000个数据
    @Override
    public Map<String, ExecutionContext> partition(int gridSize) {
        String text = "----DBToDBPartitioner---第%s分区-----开始:%s---结束:%s---数据量:%s--------------";

        Map<String, ExecutionContext> map = new HashMap<>();
        int from = 1;
        int to = DBToDBJobConfig.RANGE;
        int range = DBToDBJobConfig.RANGE;

        for (int i = 0; i < gridSize; i++) {
            System.out.println(String.format(text, i, from, to, (to - from + 1)));
            ExecutionContext context = new ExecutionContext();
            context.putInt("from", from);
            context.putInt("to", to);
            context.putInt("range", range);

            from += range;
            to += range;

            map.put("partition_" + i, context);
        }
        return map;
    }
}

步骤4:修改JobController 类

@GetMapping("/dbToDB")
public String dbToDB() throws Exception {
    employeeService.truncateAll();
    JobParameters jobParameters = new JobParametersBuilder(new JobParameters(),jobExplorer)
        .addLong("time", new Date().getTime())
        .getNextJobParameters(dbToDBJob).toJobParameters();
    JobExecution run = jobLauncher.run(dbToDBJob, jobParameters);
    return run.getId().toString();
}

步骤8:访问:http://localhost:8080/dbToDB

----DBToDBPartitioner---第0分区-----开始:1---结束:10000---数据量:10000--------------
----DBToDBPartitioner---第1分区-----开始:10001---结束:20000---数据量:10000--------------
----DBToDBPartitioner---第2分区-----开始:20001---结束:30000---数据量:10000--------------
----DBToDBPartitioner---第3分区-----开始:30001---结束:40000---数据量:10000--------------
----DBToDBPartitioner---第4分区-----开始:40001---结束:50000---数据量:10000--------------
----DBToDBPartitioner---第5分区-----开始:50001---结束:60000---数据量:10000--------------
----DBToDBPartitioner---第6分区-----开始:60001---结束:70000---数据量:10000--------------
----DBToDBPartitioner---第7分区-----开始:70001---结束:80000---数据量:10000--------------
----DBToDBPartitioner---第8分区-----开始:80001---结束:90000---数据量:10000--------------
----DBToDBPartitioner---第9分区-----开始:90001---结束:100000---数据量:10000--------------
----DBToDBPartitioner---第10分区-----开始:100001---结束:110000---数据量:10000--------------
----DBToDBPartitioner---第11分区-----开始:110001---结束:120000---数据量:10000--------------
----DBToDBPartitioner---第12分区-----开始:120001---结束:130000---数据量:10000--------------
----DBToDBPartitioner---第13分区-----开始:130001---结束:140000---数据量:10000--------------
----DBToDBPartitioner---第14分区-----开始:140001---结束:150000---数据量:10000--------------
----DBToDBPartitioner---第15分区-----开始:150001---结束:160000---数据量:10000--------------
----DBToDBPartitioner---第16分区-----开始:160001---结束:170000---数据量:10000--------------
----DBToDBPartitioner---第17分区-----开始:170001---结束:180000---数据量:10000--------------
----DBToDBPartitioner---第18分区-----开始:180001---结束:190000---数据量:10000--------------
----DBToDBPartitioner---第19分区-----开始:190001---结束:200000---数据量:10000--------------
----DBToDBPartitioner---第20分区-----开始:200001---结束:210000---数据量:10000--------------
----DBToDBPartitioner---第21分区-----开始:210001---结束:220000---数据量:10000--------------
----DBToDBPartitioner---第22分区-----开始:220001---结束:230000---数据量:10000--------------
----DBToDBPartitioner---第23分区-----开始:230001---结束:240000---数据量:10000--------------
----DBToDBPartitioner---第24分区-----开始:240001---结束:250000---数据量:10000--------------
----DBToDBPartitioner---第25分区-----开始:250001---结束:260000---数据量:10000--------------
----DBToDBPartitioner---第26分区-----开始:260001---结束:270000---数据量:10000--------------
----DBToDBPartitioner---第27分区-----开始:270001---结束:280000---数据量:10000--------------
----DBToDBPartitioner---第28分区-----开始:280001---结束:290000---数据量:10000--------------
----DBToDBPartitioner---第29分区-----开始:290001---结束:300000---数据量:10000--------------
----DBToDBPartitioner---第30分区-----开始:300001---结束:310000---数据量:10000--------------
----DBToDBPartitioner---第31分区-----开始:310001---结束:320000---数据量:10000--------------
----DBToDBPartitioner---第32分区-----开始:320001---结束:330000---数据量:10000--------------
----DBToDBPartitioner---第33分区-----开始:330001---结束:340000---数据量:10000--------------
----DBToDBPartitioner---第34分区-----开始:340001---结束:350000---数据量:10000--------------
----DBToDBPartitioner---第35分区-----开始:350001---结束:360000---数据量:10000--------------
----DBToDBPartitioner---第36分区-----开始:360001---结束:370000---数据量:10000--------------
----DBToDBPartitioner---第37分区-----开始:370001---结束:380000---数据量:10000--------------
----DBToDBPartitioner---第38分区-----开始:380001---结束:390000---数据量:10000--------------
----DBToDBPartitioner---第39分区-----开始:390001---结束:400000---数据量:10000--------------
----DBToDBPartitioner---第40分区-----开始:400001---结束:410000---数据量:10000--------------
----DBToDBPartitioner---第41分区-----开始:410001---结束:420000---数据量:10000--------------
----DBToDBPartitioner---第42分区-----开始:420001---结束:430000---数据量:10000--------------
----DBToDBPartitioner---第43分区-----开始:430001---结束:440000---数据量:10000--------------
----DBToDBPartitioner---第44分区-----开始:440001---结束:450000---数据量:10000--------------
----DBToDBPartitioner---第45分区-----开始:450001---结束:460000---数据量:10000--------------
----DBToDBPartitioner---第46分区-----开始:460001---结束:470000---数据量:10000--------------
----DBToDBPartitioner---第47分区-----开始:470001---结束:480000---数据量:10000--------------
----DBToDBPartitioner---第48分区-----开始:480001---结束:490000---数据量:10000--------------
----DBToDBPartitioner---第49分区-----开始:490001---结束:500000---数据量:10000--------------
----------MyBatisPagingItemReader开始-----from: 250001  -----to:260000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 290001  -----to:300000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 80001  -----to:90000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 410001  -----to:420000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 360001  -----to:370000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 230001  -----to:240000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 40001  -----to:50000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 340001  -----to:350000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 450001  -----to:460000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 110001  -----to:120000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 350001  -----to:360000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 50001  -----to:60000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 430001  -----to:440000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 20001  -----to:30000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 120001  -----to:130000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 190001  -----to:200000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 100001  -----to:110000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 470001  -----to:480000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 60001  -----to:70000  -----每片数量:10000
----------MyBatisPagingItemReader开始-----from: 200001  -----to:210000  -----每片数量:10000

到这,案例就全部结束了。

转视频版

看文字不过瘾可以切换视频版:Spring Batch高效批处理框架实战

猜你喜欢

转载自blog.csdn.net/langfeiyes/article/details/129289391