前景: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(); }