本文根據《SpringBatch批處理框架》一書作者劉相的源碼升級spring4.0,源碼爲3.2版本
經測試可用
提示:本文源碼比較多
遇到的問題總結在後面
配置
數據庫初始化 create-tables-mysql.sql
DROP TABLE IF EXISTS t_credit;
DROP TABLE IF EXISTS t_destcredit;
CREATE TABLE t_credit
(ID VARCHAR(64),
ACCOUNTID VARCHAR(20),
NAME VARCHAR(10),
AMOUNT NUMERIC(10,2),
DATE VARCHAR(20),
ADDRESS VARCHAR(128),
FLAG VARCHAR(10),
primary key (ID)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE t_destcredit
(ID VARCHAR(64),
ACCOUNTID VARCHAR(20),
NAME VARCHAR(10),
AMOUNT NUMERIC(10,2),
DATE VARCHAR(20),
ADDRESS VARCHAR(128),
primary key (ID)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('01','4047390012345678','tom',100.00,'2013-2-2 12:00:08','Lu Jia Zui road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('02','4047390012345678','tom',320.00,'2013-2-3 10:35:21','Lu Jia Zui road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('03','4047390012345678','tom',674.70,'2013-2-6 16:26:49','South Linyi road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('04','4047390012345678','tom',793.20,'2013-2-9 15:15:37','Longyang road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('05','4047390012345678','tom',360.00,'2013-2-11 11:12:38','Longyang road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('06','4047390012345678','tom',100.00,'2013-2-2 12:00:08','Lu Jia Zui road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('07','4047390012345678','tom',320.00,'2013-2-3 10:35:21','Lu Jia Zui road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('08','4047390012345678','tom',674.70,'2013-2-6 16:26:49','South Linyi road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('09','4047390012345678','tom',793.20,'2013-2-9 15:15:37','Longyang road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('10','4047390012345678','tom',360.00,'2013-2-11 11:12:38','Longyang road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('11','4047390012345678','tom',100.00,'2013-2-2 12:00:08','Lu Jia Zui road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('12','4047390012345678','tom',320.00,'2013-2-3 10:35:21','Lu Jia Zui road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('13','4047390012345678','tom',674.70,'2013-2-6 16:26:49','South Linyi road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('14','4047390012345678','tom',793.20,'2013-2-9 15:15:37','Longyang road','false');
INSERT INTO t_credit(ID,ACCOUNTID,NAME,AMOUNT,DATE,ADDRESS,FLAG) VALUES('15','4047390012345678','tom',360.00,'2013-2-11 11:12:38','Longyang road','false');
數據庫連接配置 batch-mysql.properties
datasource.driver=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://127.0.0.1:3306/test1289
datasource.username=root
datasource.password=000000
Spring DB驅動配置 job-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:bean="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd">
<!--
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:db/create-tables-mysql.sql" />
</jdbc:initialize-database>
-->
<!--
<bean:bean id="simpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<bean:constructor-arg ref="dataSource" />
</bean:bean>
-->
<bean:bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<bean:constructor-arg ref="dataSource" />
</bean:bean>
</bean:beans>
Bean定義 job-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:bean="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.0.xsd">
<context:property-placeholder location="classpath:db/batch-mysql.properties" />
<bean:bean
class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<bean:property name="jobRegistry" ref="jobRegistry" />
</bean:bean>
<bean:bean id="stepLocator"
class="org.springframework.batch.integration.partition.BeanFactoryStepLocator" />
<bean:bean id="jobRegistry"
class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
<bean:bean id="jobExplorer"
class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean">
<bean:property name="dataSource" ref="dataSource" />
</bean:bean>
<bean:bean id="jobOperator"
class="org.springframework.batch.core.launch.support.SimpleJobOperator">
<bean:property name="jobRepository" ref="jobRepository" />
<bean:property name="jobLauncher" ref="jobLauncher" />
<bean:property name="jobRegistry" ref="jobRegistry" />
<bean:property name="jobExplorer" ref="jobExplorer" />
</bean:bean>
<!-- "SERIALIZABLE" -->
<job-repository id="jobRepository" data-source="dataSource"
transaction-manager="transactionManager" isolation-level-for-create="READ_COMMITTED"
table-prefix="BATCH_" max-varchar-length="1000"
/>
<bean:bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<bean:property name="jobRepository" ref="jobRepository"/>
</bean:bean>
<bean:bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<bean:property name="dataSource" ref="dataSource" />
</bean:bean>
<bean:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<bean:property name="driverClassName">
<bean:value>${datasource.driver}</bean:value>
</bean:property>
<bean:property name="url">
<bean:value>${datasource.url}</bean:value>
</bean:property>
<bean:property name="username" value="${datasource.username}"></bean:property>
<bean:property name="password" value="${datasource.password}"></bean:property>
</bean:bean>
</bean:beans>
Batch的分區任務配置 job-partition-db.xml
<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:bean="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-3.0.xsd">
<bean:import resource="classpath:db/job-context.xml"/>
<bean:import resource="classpath:db/job-context-db.xml"/>
<job id="partitionJob" restartable="true">
<step id="partitionStep">
<partition step="partitionReadWriteDB" partitioner="partitionerDB">
<handler grid-size="4" task-executor="taskExecutor"/>
</partition>
</step>
</job>
<step id="partitionReadWriteDB">
<tasklet >
<chunk reader="jdbcItemPageReader" writer="jdbcItemWriter"
processor="creditBillProcessor" commit-interval="2"/>
<listeners>
<listener ref="partitionItemReadListener"></listener>
</listeners>
</tasklet>
</step>
<!-- db數據切分 -->
<bean:bean id="partitionerDB"
class="com.demo.report.settle.DBpartition">
<bean:property name="table" value="t_credit"/>
<bean:property name="column" value="DID"/>
<bean:property name="dataSource" ref="dataSource"/>
</bean:bean>
<!-- 從db分頁讀數據 -->
<bean:bean id="jdbcItemPageReader" scope="step"
class="org.springframework.batch.item.database.JdbcPagingItemReader">
<bean:property name="dataSource" ref="dataSource"/>
<bean:property name="queryProvider" ref="refQueryProvider" />
<bean:property name="pageSize" value="2"/>
<bean:property name="rowMapper" ref="custCreditRowMapper"/>
</bean:bean>
<bean:bean id="refQueryProvider" scope="step"
class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
<bean:property name="dataSource" ref="dataSource"/>
<bean:property name="selectClause" value="select DID,ACCOUNTID,INNAME,AMOUNT,INDATE,ADDRESS"/>
<bean:property name="fromClause" value="from t_credit"/>
<bean:property name="whereClause" value="where MOD(DID,#{stepExecutionContext[_grideSize]}) = #{stepExecutionContext[_curPartition]} AND DID between #{stepExecutionContext[_minRecord]} and #{stepExecutionContext[_maxRecord]}"/>
<bean:property name="sortKey" value="DID"/>
</bean:bean>
<bean:bean id="custCreditRowMapper"
class="com.demo.report.settle.CreditBillRowMapper"/>
<bean:bean id="jdbcItemWriter"
class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<bean:property name="dataSource" ref="dataSource"/>
<bean:property name="sql" value="insert into t_destcredit (DID,ACCOUNTID,INNAME,AMOUNT,INDATE,ADDRESS) values (:id,:accountID,:name,:amount,:date,:address)"/>
<bean:property name="itemSqlParameterSourceProvider">
<bean:bean class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider"/>
</bean:property>
</bean:bean>
<bean:bean id="creditBillProcessor" scope="step"
class="com.demo.report.settle.CreditBillProcessor">
</bean:bean>
<bean:bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<bean:property name="corePoolSize" value="5"/>
<bean:property name="maxPoolSize" value="15"/>
</bean:bean>
<bean:bean id="partitionItemReadListener"
class="com.demo.report.settle.PartitionStepExecutionListener">
</bean:bean>
</bean:beans>
源碼
數據源PoJo-CreditBill.java
/**
*
*/
package com.demo.report.settle;
import java.io.Serializable;
/**
* 信用卡對賬單模型.<br>
*
* @author bruce.liu(mailto:[email protected])
* 2014-1-11下午02:29:58
*/
public class CreditBill implements Serializable{
/**
*
*/
private static final long serialVersionUID = -4940717436114184875L;
private String id;
private String accountID = ""; /** 銀行卡賬戶ID */
private String name = ""; /** 持卡人姓名 */
private double amount = 0; /** 消費金額 */
private String date; /** 消費日期 ,格式YYYY-MM-DD HH:MM:SS*/
private String address; /** 消費場所 **/
public CreditBill(){}
public CreditBill(String accountID, String name, double amount, String date, String address){
this.accountID = accountID;
this.name = name;
this.amount = amount;
this.date = date;
this.address = address;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAccountID() {
return accountID;
}
public void setAccountID(String accountID) {
this.accountID = accountID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
/**
*
*/
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append("id=" + getId() + ";accountID=" + getAccountID() + ";name=" + getName() + ";amount="
+ getAmount() + ";date=" + getDate() + ";address=" + getAddress());
return sb.toString();
}
}
接收方PoJo DestinationCreditBill.java
/**
*
*/
package com.demo.report.settle;
import java.io.Serializable;
/**
*
* @author bruce.liu(mailto:[email protected])
* 2014-1-11下午02:37:55
*/
public class DestinationCreditBill implements Serializable{
/**
*
*/
private static final long serialVersionUID = 5253572139260172440L;
private String id;
private String accountID = ""; /** 銀行卡賬戶ID */
private String name = ""; /** 持卡人姓名 */
private double amount = 0; /** 消費金額 */
private String date; /** 消費日期 ,格式YYYY-MM-DD HH:MM:SS*/
private String address; /** 消費場所 **/
public DestinationCreditBill(){}
public DestinationCreditBill(String accountID, String name, double amount, String date, String address){
this.accountID = accountID;
this.name = name;
this.amount = amount;
this.date = date;
this.address = address;
}
public String getAccountID() {
return accountID;
}
public void setAccountID(String accountID) {
this.accountID = accountID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/**
*
*/
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append("accountID=" + getAccountID() + ";name=" + getName() + ";amount="
+ getAmount() + ";date=" + getDate() + ";address=" + getAddress());
return sb.toString();
}
}
分區步驟監視器 PartitionStepExecutionListener.java
/**
*
*/
package com.demo.report.settle;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
/**
*
* @author bruce.liu(mailto:[email protected])
* 2014-3-22上午10:11:29
*/
public class PartitionStepExecutionListener implements StepExecutionListener {
@Override
public void beforeStep(StepExecution stepExecution) {
System.out.println("ThreadName=" + Thread.currentThread().getName() + "; "
+ "StepName=" + stepExecution.getStepName() + ";");
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
}
查詢結果集轉換器 CreditBillRowMapper.java
/**
*
*/
package com.demo.report.settle;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.demo.report.settle.CreditBill;
/**
*
* @author bruce.liu(mailto:[email protected])
* 2014-1-11下午03:10:28
*/
public class CreditBillRowMapper implements RowMapper<CreditBill> {
public CreditBill mapRow(ResultSet rs, int rowNum) throws SQLException {
CreditBill bill = new CreditBill();
bill.setId(rs.getString("DID"));
bill.setAccountID(rs.getString("ACCOUNTID"));
bill.setAddress(rs.getString("ADDRESS"));
bill.setAmount(rs.getDouble("AMOUNT"));
bill.setDate(rs.getString("INDATE"));
bill.setName(rs.getString("INNAME"));
return bill;
}
}
分區策略生成器 DBpartition.java
package com.demo.report.settle;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.batch.core.partition.support.Partitioner;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.jdbc.core.JdbcTemplate;
/**
*
* @author bruce.liu(mailto:[email protected])
* 2014-1-11下午03:13:45
*/
public class DBpartition implements Partitioner {
private static final String _MINRECORD = "_minRecord";
private static final String _MAXRECORD = "_maxRecord";
private static final String _GRIDSIZE = "_grideSize";
private static final String _CURPARTITION = "_curPartition";
private static final String MIN_SELECT_PATTERN = "select min({0}) from {1}";
private static final String MAX_SELECT_PATTERN = "select max({0}) from {1}";
private JdbcTemplate jdbcTemplate ;
private DataSource dataSource;
private String table ;
private String column;
public Map<String, ExecutionContext> partition(int gridSize) {
validateAndInit();
Map<String, ExecutionContext> resultMap = new HashMap<String, ExecutionContext>();
int min = jdbcTemplate.queryForObject(MessageFormat.format(MIN_SELECT_PATTERN, new Object[]{column,table}),Integer.class);
int max = jdbcTemplate.queryForObject(MessageFormat.format(MAX_SELECT_PATTERN, new Object[]{column,table}),Integer.class);
int targetSize = (max-min)/gridSize +1;
int number=0;
int start =min;
int end = start+targetSize-1;
while(start <= max){
ExecutionContext context = new ExecutionContext();
if(end>=max){
end=max;
}
context.putInt(_MINRECORD, start);
context.putInt(_MAXRECORD, end);
context.putLong(_CURPARTITION, Thread.currentThread().getId());
context.putInt(_GRIDSIZE, gridSize);
start+=targetSize;
end+=targetSize;
resultMap.put("partition"+(number++), context);
}
System.out.println("gridSize is ="+gridSize+"***current thread id is "+Thread.currentThread().getId()+"*** name is "+Thread.currentThread().getName());
if(!resultMap.isEmpty())
{
resultMap.forEach((k,v)->{System.out.println("key is "+k+"****values is"+v);});
}
return resultMap;
}
public void validateAndInit(){
if(isEmpty(table)){
throw new IllegalArgumentException("table cannot be null");
}
if(isEmpty(column)){
throw new IllegalArgumentException("column cannot be null");
}
if(dataSource!=null && jdbcTemplate==null){
jdbcTemplate = new JdbcTemplate(dataSource);
}
if(jdbcTemplate==null){
throw new IllegalArgumentException("jdbcTemplate cannot be null");
}
}
public static boolean isEmpty(String info){
if(info!=null){
if(info.trim().length()>1){
return false;
}
}
return true;
}
public String getColumn() {
return column;
}
public void setColumn(String column) {
this.column = column;
}
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
分區處理器 CreditBillProcessor.java
/**
*
*/
package com.demo.report.settle;
import org.springframework.batch.item.ItemProcessor;
/**
*
* @author bruce.liu(mailto:[email protected])
* 2014-1-11下午02:38:01
*/
public class CreditBillProcessor implements
ItemProcessor<CreditBill, DestinationCreditBill> {
public DestinationCreditBill process(CreditBill bill) throws Exception {
System.out.println(bill.toString());
DestinationCreditBill destCreditBill = new DestinationCreditBill();
destCreditBill.setAccountID(bill.getAccountID());
destCreditBill.setAddress(bill.getAddress());
destCreditBill.setAmount(bill.getAmount());
destCreditBill.setDate(bill.getDate());
destCreditBill.setId(bill.getId());
destCreditBill.setName(bill.getName());
return destCreditBill;
}
}
測試類基類 JobLaunchBase.java
package com.snail.report.settle;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*
*/
/**
* @author bruce.liu(mailto:[email protected])
* 2013-9-7下午01:57:02
*/
public class JobLaunchBase {
private static ApplicationContext context;
/**
* 執行批處理作業.<br>
* @param jobPath 作業配置文件
* @param jobName 作業名
* @param builder 作業參數構造器
*/
public static void executeJob(String jobPath, String jobName, JobParametersBuilder builder) {
context = new ClassPathXmlApplicationContext(jobPath);
JobLauncher launcher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean(jobName);
try {
JobExecution result = launcher.run(job, builder.toJobParameters());
System.out.println(result.toString());
} catch (Exception e) {
e.printStackTrace();
}finally {
context=null;
job=null;
builder=null;
launcher=null;
}
}
}
測試類 JobLaunchPartitionDBOracle.java
package com.snail.report.settle;
/**
*
*/
import java.util.Date;
import org.springframework.batch.core.JobParametersBuilder;
import com.snail.report.settle.JobLaunchBase;
/**
*
* @author bruce.liu(mailto:[email protected])
* 2013-11-16下午10:59:46
*/
public class JobLaunchPartitionDBOracle {
/**
* @param args
*/
public static void main(String[] args) {
JobLaunchBase.executeJob("db/job-partition-db.xml", "partitionJob",
new JobParametersBuilder().addDate("date", new Date()));
System.exit(0);
}
}
問題總結
找不到batch
原因是創建spring boot項目時忘記加batch了
<spring.batch.version>3.2.1.RELEASE</spring.batch.version>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>${spring.batch.version}</version>
<type>jar</type>
<optional>false</optional>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>${spring.batch.version}</version>
<type>jar</type>
<optional>false</optional>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-integration</artifactId>
<version>1.2.0.RELEASE</version>
<optional>false</optional>
</dependency>
找不到oracle驅動
手工加入maven倉庫
mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc14 -Dversion=10.2.0.1.0 -Dpackaging=jar -Dfile=ojdbc14-10.2.0.1.0.jar
無法連續事務處理
ORA-08177: 無法連續訪問此事務處理 batch
org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:131)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
解決辦法 job-repository 改事務級別
<!-- 原來是這個 "SERIALIZABLE" -->
<job-repository id="jobRepository" data-source="dataSource"
transaction-manager="transactionManager" isolation-level-for-create="READ_COMMITTED"
table-prefix="BATCH_" max-varchar-length="1000"
/>
jdbcTemplate找不到 queryForInt 方法
The method queryForInt(String) is undefined for the type JdbcTemplate DBpartition.java
因爲使用spring4,默認jdbc版本也高了,原有的方法沒了,所以解決辦法是改成 jdbcTemplate.queryForObject 注意要新加一個參數是 返回對象的類型
int max = jdbcTemplate.queryForObject(MessageFormat.format(MAX_SELECT_PATTERN, new Object[]{column,table}),**Integer.class**);
加了mod,細化分區
加這個算是一點試驗,剛開始沒注意到變量名的問題,執行錯誤,後來發現
配置文件中的where條件如果取變量值 ,需要stepExecutionContext+變量名 纔可以
參考我加的**_grideSize**就明白了。
總結
總體來說改造難度不大,下一次版本應該是註解版的了,或許挑戰一下分區多線程。
推薦文章
http://www.kailing.pub/article/index/arcid/196.html
https://www.cnblogs.com/softidea/p/7142084.html