/**
* 为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 四个字段