前景:DB2数据库、Mybatis、数据插入。
也不知道这样做合不合理。欢迎指导*.*
<insert id="batchAddPlan">
INSERT INTO TB_POC_C_PLAN_ALLYEAR(ID,VERSIONS,YEAR,MONTH,PLAN_DATE,WEEK,WEEK_DAT,CAR_ID,ASSEMBLY,COUNT,CREATER,CREATER_DATE,NAME,VERSION_NAME) VALUES
<foreach collection="list" item="item" index="index" separator=",">
(NEXTVAL FOR ID_SEQ,#{item.versions},#{item.year},#{item.month},#{item.planDate},#{item.week},#{item.weekDat},NULL,NULL,#{item.count},#{username},CURRENT DATE,#{item.name},#{item.versionName})
</foreach>
</insert>
执行后报错:SQL statement too long or complex. (原因是ibatis动态生成的sql很长)
后来同事说可以使用多线程插入,这里没有使用继承Thread或实现Runable接口,而是使用的Callable<V>接口。
大致的思路是:
将原来的数据分割成多个子数据集合
每个子数据集合放到一个线程中执行
每个线程返回一个值:正常返回0;错误返回-1
多个线程的返回值和为0则正常,否则抛出异常,执行数据库事务。
线程类如下:
class ConCurrentDB2Insert implements Callable<Integer> {
private List<AllYearPlan> parameters;
private String username;
ConCurrentDB2Insert(List<AllYearPlan> parameters, String username) {
this.parameters = parameters;
this.username = username;
}
@Override
public Integer call() throws Exception {
try {
dao.batchAddPlan(this.parameters, this.username);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
return 0;
}
}
执行上述类的方法如下:
private boolean execute(String username, List<AllYearPlan>...args) throws Exception{
ExecutorService exec = Executors.newCachedThreadPool();
int sum = 0;
List<Future<Integer>> results = new ArrayList<Future<Integer>>();
for (int i = 0; i < args.length; i++) {
results.add(exec.submit(new ConCurrentDB2Insert(args[i], username)));
}
for (Future<Integer> result: results) {
if (result.isDone()) {
sum += result.get();
}
}
exec.shutdown();
return sum==0?true:false;
}
分割数据包的类如下:
/**
* List分割类
* @param <T>
*/
class ListSplit<T> {
private List<T> list;
private int pageSize;
private int pageCount;
private int totalCount;
private int m;
private List<T>[] results;
public ListSplit(List<T> list, int pageSize) {
this.list = list;
this.pageSize = pageSize;
this.pageCount = 0;
this.totalCount = list.size();
this.m = totalCount%pageSize;
}
public List<T>[] split() {
if (m>0) {
pageCount=totalCount/pageSize+1;
} else {
pageCount=totalCount/pageSize;
}
this.results = new List[pageCount];
for(int i=1;i<=pageCount;i++){
if (m==0) {
List<T> subList= list.subList((i-1)*pageSize,pageSize*(i));
this.results[i-1] = subList;
} else {
if (i==pageCount) {
List<T> subList= list.subList((i-1)*pageSize,totalCount);
this.results[i-1] = subList;
} else {
List<T> subList= list.subList((i-1)*pageSize,pageSize*(i));
this.results[i-1] = subList;
}
}
}
return this.results;
}
}
具体调用方法如下:
try {
this.execute(username, new ListSplit<AllYearPlan>(parameters, 100).split());
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}