楼主使用的 sqlserver 数据库,不支持 insert or uodate,但是楼主需要完成批量的数据操作,从前端拿到数据集合,从数据库拿到已有的数据集合,进行比对,如果主键相同并且其他字段不同,则进行更新,如果所有字段都相同即忽略,其他情况就都是插入,以下的图是数据示例:
【方法一】
这里说明一下,由于是因为使用了sqlerver 数据库,数据相同的情况下进行update 会返回1 也就是数据库仍然会进行一次操作。在mysql里则会返回0,所以如果是使用的mysql,就不用考虑数据相同的情况了,直接update即可
for (Map data : incomeData) { //遍历从前端拿到的数据
boolean bo_insert = false; //标记是否做插入操作
boolean bo_update = false; //标记是否需要更新
boolean bo_nothing = false;
String staff_id2 = (String)data.get("staff_id");
String yearmon2 = (String)data.get("yearmon");
BigDecimal ratio2 ;
if (data.get("ratio") instanceof Double) {
ratio2 = new BigDecimal((Double)data.get("ratio"));
}else{
ratio2 = new BigDecimal((Integer)data.get("ratio"));
}
for (Map map : ratioList) { //遍历从数据库拿到的数据
String staff_id = (String)map.get("staff_id");
String yearmon = (String)map.get("yearmon");
BigDecimal ratio = (BigDecimal)map.get("ratio");
//主键相同且其他字段不相同,标记为 更新
if (staff_id.equals(staff_id2)&&yearmon.equals(yearmon2)&&ratio2.compareTo(ratio)!=0) {bo_update = true;}
//全部字段相同,标记为 忽略
if (staff_id.equals(staff_id2)&&yearmon.equals(yearmon2)&&ratio2.compareTo(ratio)==0) {bo_nothing = true;}
}
//不是更新操作 也不是忽略操作,标记为插入
if (!bo_update&&!bo_nothing) {bo_insert = true;}
if (bo_insert) {//插入操作
}
if(bo_update){//修改操作
}
}
【方法二(推荐)】
原本的数据结构(示例):
[{rdproj_id:1001,yearmon:201801,staff_id:2001,ratio:0.5},{rdproj_id:1001,yearmon:201802,staff_id:2001,ratio:0.8}]
现在将其改造成以下结构
{1001:{{201801:{2001:0.5}},{201802:{2001:0.8}}}}
这样我们就可以通过一层一层的 map.get("")方法来进行比较,比如,我现在想要比较的数据是
{rdproj_id:1002,yearmon:201801,staff_id:2001,ratio:0.5}
那么,很明显在第一层 map.get("1002")时就会返回null,那么,这一组数据可以直接判定为insert操作。
注意:在这个方法里,我没有再去忽略完全相同的记录。将其归为了update
public class MemoryContainer {
//准备一个内存容器
public static Map<String, Map<String, Map<String, Double>>> staffRatioMap = new HashMap<String, Map<String, Map<String, Double>>>();
//准备一个将list转为map
public static void putStaffRatioMap(List<Map> ratioList){
for (Map map : ratioList) {
String project_id = (String) map.get("rdproj_id");
String ym = (String) map.get("yearmon");
String staff_id = (String) map.get("staff_id");
Double ratio ;
if (map.get("ratio") instanceof Double) {
ratio = (Double)map.get("ratio");
}else if (map.get("ratio") instanceof Integer) {
int r = (Integer)map.get("ratio");
if (r==0) {ratio = 0.0;}else{ratio = 1.0;}
}else {
BigDecimal r = (BigDecimal)map.get("ratio");
ratio = r.doubleValue();
}
Map<String, Map<String, Double>> ymmap;
Map<String, Double> smap;
if (CMYUtils.isEmpty(ymmap = MemoryContainer.staffRatioMap.get(project_id))){
smap = new HashMap<String, Double>();
smap.put(staff_id, ratio);
ymmap = new HashMap<String, Map<String, Double>>();
ymmap.put(ym, smap);
MemoryContainer.staffRatioMap.put(project_id, ymmap);
} else {
if (CMYUtils.isEmpty(smap = ymmap.get(ym))) {
smap = new HashMap<String, Double>();
smap.put(staff_id, ratio);
ymmap.put(ym, smap);
} else {
if(CMYUtils.isEmpty(smap.get(staff_id))){
smap.put(staff_id,ratio);
}
}
}
}
}
}
Map<String, Map<String, Map<String, Double>>> menoryRec = MemoryContainer.staffRatioMap;
if (menoryRec.size()==0) {//如果内存中没有,查数据库,并且存入内存
List<Map> ratioList = businessMapper.selectStaffRatio(inDto);
MemoryContainer.putStaffRatioMap(ratioList);
menoryRec = MemoryContainer.staffRatioMap;
}
Map<String, Map<String, Double>> rec = menoryRec.get(incomeData.get(0).get("rdproj_id"));
if (CMYUtils.isEmpty(rec)) { //如果第一层比对就为null,做插入操作
MemoryContainer.putStaffRatioMap(incomeData);
for (Map webData : incomeData) {
//insert方法
}
}else{
for (Map webData : incomeData) { //遍历 前台拿到的数据
boolean bo_insert = true;
String webStaff = (String)webData.get("staff_id");
String webYearMon = (String)webData.get("yearmon");
Double ratioDouble;
if (webData.get("ratio") instanceof Double) {
ratioDouble = (Double)webData.get("ratio");
}else {
if ((Integer)webData.get("ratio")==1) {
ratioDouble = 1.0;
}else{
ratioDouble = 0.0;
}
}
if (CMYUtils.isNotEmpty(rec.get(webYearMon))) {
Map<String, Double> staff = (Map) rec.get(webYearMon);
if (CMYUtils.isNotEmpty(staff.get(webStaff))) {bo_insert = false;}//标记为更新操作
staff.put(webStaff, ratioDouble);//往内存存入数据,有则覆盖(修改),无则添加
}else{
Map<String,Double> sMap = new HashMap<String, Double>();
sMap.put(webStaff, ratioDouble);
rec.put(webYearMon, sMap);//往内存添加数据。
}
if (bo_insert) {
//insert方法
}else {
//更新方法
}
}
}
我在做更新或者插入操作的同时,内存容器 staffRatioMap 也在做同样的动作,所以,在下一次调用这个方法时,staffRatioMap里的数据和数据库是同步的,在项目重启前完全不需要再访问数据库了。