/** * 为model的每个属性生成一个index * @param model * @return */ public static Map<String, Integer> orderKey(Model<?> model) { Map<String, Integer> map = new HashMap<String, Integer>(); Set<String> set = CPI.getTable(model).getColumnNameSet(); int index = 0; for(String key : set) { map.put(key, index++); } return map; } /** * 给每个model生成一个key用于分类 * 根据model内值不为空的属性对应index进行组合 * @param model * @param orderKey * @return */ public static int batchKey(Model<?> model, Map<String, Integer> orderKey) { Set<Entry<String, Object>> entrySet = model._getAttrsEntrySet(); int[] array = new int[entrySet.size()]; for(Entry<String, Object> entry : entrySet) { if(entry.getValue() != null) { array[orderKey.get(entry.getKey())] = 1; } } return binary(array); } public static int binary(int[] array) { StringBuilder sb = new StringBuilder(); for (int s : array) { sb.append(s); } return Integer.parseInt(sb.toString(), 2); } /** * 分类执行批量处理 * @param list * @return */ public static List<int[]> batch(List<Model<?>> list) { Map<String, Integer> orderKey = orderKey(list.get(0)); Map<Integer, List<Model<?>>> batchMap = new HashMap<Integer, List<Model<?>>>(); for(Model<?> model : list) { int mapKey = batchKey(model, orderKey); List<Model<?>> batchList = batchMap.get(mapKey); if(batchList == null) { batchList = batchMap.put(mapKey, new ArrayList<Model<?>>()); } batchList.add(model); } List<int[]> returns = new ArrayList<int[]>(); batchMap.forEach((key, value) -> returns.add(Db.batchUpdate(value, 100))); return returns; }
代码没测试过,只提供思路。
主要就是解决Db批量更新时,集合内每个model的属性值不一致导致有些model的属性更新时漏掉。
那么,把集合内每个model根据每个属性是否有值进行分类,处理成多个集合,再循环进行批处理。
但上面方法也有缺陷,因为最多字段个数的 model 在如下情况下也不能作为生成 sql 的蓝本,例如:
1:假定 model a 拥有 a,b,c 三个字段值
2:假定 model b 拥有 b,c,d 三个字段值
3:以上情况,字段值数量是一致的,但字段名本身不一致
4:当然,可以更进一步,在迭代的时候获取所有字段名来生成 sql,得到 a,b,c,d 四个字段