需求三:使用分区的方式将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高效批处理框架实战