这里是我试过的代码,但多个线程正在访问数据库中的相同数据....
MY XML
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<bean id="JobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<batch:job id="firstjob">
<batch:step id="masterStep">
<batch:partition step="step1" partitioner="rangePartitioner">
<batch:handler grid-size="1" task-executor="taskExecutor" />
</batch:partition>
</batch:step>
</batch:job>
<batch:step id="step1" xmlns="http://www.springframework.org/schema/batch">
<batch:tasklet >
<batch:chunk reader="itemReader" writer="ItemWriter" commit-interval="1" >
</batch:chunk>
</batch:tasklet>
</batch:step>
<bean id="rangePartitioner" class="com.spring.itemreader.Partioner" />
<bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseType" value="mysql" />
</bean>
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="org/springframework/batch/core/schema-drop-mysql.sql" />
<jdbc:script location="org/springframework/batch/core/schema-mysql.sql" />
</jdbc:initialize-database>
<bean id="itemReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="select id from reader where id >= ? and id <= ? " />
<property name="preparedStatementSetter" ref="readersetter"/>
<property name="rowMapper" ref="rowmapprer"/>
</bean>
<bean id="rowmapprer" class="com.spring.itemreader.rowmapprer">
<property name="data" ref="data"/>
</bean>
<bean id="data" class="com.spring.itemreader.data" />
<bean id="ItemWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="assertUpdates" value="false" />
<property name="itemPreparedStatementSetter">
<bean class="com.spring.itemwriter.setter" />
</property>
<property name="sql" value="INSERT INTO writer VALUES(?)" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="readersetter" class="com.spring.itemreader.readersetter" scope="step">
<property name="fid" value="#{stepExecutionContext[fromId]}"/>
<property name="tid" value="#{stepExecutionContext[toId]}"/>
</bean>
</beans>
,我的分区类是:
public class Partioner implements Partitioner{
@Override
public Map<String, ExecutionContext> partition(int gridSize) {
//map for storing:
Map<String, ExecutionContext> result
= new HashMap<String, ExecutionContext>();
int range = 100;
int fromId = 1;
int toId = range;
ExecutionContext value=null;
using for loop i am giving range id and ExecutionContext
for (int i = 1; i <= gridSize; i++) {
value = new ExecutionContext();
System.out.println("\nStarting : Thread" + i);
System.out.println("fromId : " + fromId);
System.out.println("toId : " + toId);
value.putInt("fromId", fromId);
value.putInt("toId", toId);
// give each thread a name, thread 1,2,3
value.putString("name", "Thread" + i);
result.put("partition" + i, value);
fromId = toId + 1;
toId += range;
}
return result;
}
和我的读者二传手 公共类readeretter实现PreparedStatementSetter {
private int fid;
private int tid;
public int getFid() {
return fid;
}
public void setFid(int fid) {
this.fid = fid;
}
public int getTid() {
return tid;
}
public void setTid(int tid) {
this.tid = tid;
}
@Override
public void setValues(PreparedStatement se) throws SQLException {
// TODO Auto-generated method stub
se.setInt(1,fid);
se.setInt(2,tid);
}
但是对于网格尺寸1以上工作正常,当我增加尺寸时它不起作用,请帮助解决这个问题......
当我增加网格大小时,这就是面对的问题
开始:Thread1 开始:1 结束:110
开始:Thread2 开始:111 结束:220
开始:Thread3 开始:221 结束:330
开始:Thread4 开始:331 结束:440
开始:Thread5 开始:441 结束:550
错误 PreparedStatementCallback; SQL [INSERT INTO writer VALUES(?)];键'PRIMARY'重复输入'331';嵌套异常是java.sql.BatchUpdateException:键'PRIMARY'的重复条目'331'
就像每次都得到相同的错误一样,访问DB时其他线程范围也会改变....
Rowmapper和WriterSetter的Sysout 开始:Thread1 fromId:1 toId: 220
开始:Thread2 fromId:221 toId: 440
row mapper221
row mapper1
writer1
writer1
row mapper2
writer2
row mapper3
答案 0 :(得分:0)
我认为问题出在您的分区逻辑中。请使用以下内容更改您的for循环。
for (int i = 1; i <= gridSize; i++) {
toId = fromId + blocksize;
ExecutionContext value = new ExecutionContext();
if (fromId > totalRecords) {
break;
}
if (toId > totalRecords) {
toId = totalRecords;
System.out.println("\nStarting : Thread" + i);
System.out.println("fromId : " + fromId);
System.out.println("toId : " + toId);
value.putDouble("fromId", fromId);
value.putDouble("toId", toId);
// give each thread a name, thread 1,2,3
value.putString("name", "Thread" + i);
result.put("partition" + i, value);
break;
} else {
System.out.println("\nStarting : Thread" + i);
System.out.println("fromId : " + fromId);
System.out.println("toId : " + toId);
value.putDouble("fromId", fromId);
value.putDouble("toId", toId);
value.putString("name", "Thread" + i);
result.put("partition" + i, value);
fromId = toId + 1;
}
}