最近工作遇到一个问题,数据重复插入到DB,前端和后端都做了表单防止重复提交功能,依然还是在并发场景或者网络延迟的场景下,数据还是会重复插入。
项目中在新增数据前做了一次查询,因为数据库内容比较多,导致查询会有延迟,所以导致了提交相同的数据,拦截不掉
也阅读了一些其他大神的方法,基本都是加锁或者是对数据库做改动,这里我在代码层度里提出一种解决方法。
我们可以在全局定义一个hashmap
//缓存表单里提交的信息
private Map<String, JSONObject> Map = new HashMap<>();
这里不是缓存所有传过来的参数,我们可以根据数据库字段来选一个最合适的,我们的项目是一个评价系统,所以这里我们选择评价次数这个字段来存到map里,具体逻辑流程看下面的代码
// 拦截重复提交数据
//将数据库中唯一的字段作为key
String key = id;
这里代码的意思是第一次提交的请求这个map里是空的,我们先做一次判断,如果这
map是空的,我们就把id作为key,json封装的参数数据作为value存到map里,
然后行接下来的业务逻辑
if (!Map.containsKey(key)) {
Map.put(key, jsonparam);
} else {
如果map里存在数据,我们会拿这个第二次传过来的json里面的字段和这个存在map里的
这个字段做对比,如果判断不过,我们就不让第二次的数据插入
String str1 = (String) Map.get(key).get("evaluteCount");
int num1 = Integer.parseInt(str1);
String str2 = json.getString("evaluteCount");
int num2 = Integer.parseInt(str2);
if (num2<=num1) {
return rsp(false, "请勿重复提交",null);
}
}
第一点注意!!!!!!!!!!!!!!
第一次进来的数据,入库成功后,记得清除map!!!
// 保存成功后 清除map
if (doSave) {
Map.remove(key);
第二点注意!!!!!!!!!!!!!!
如果我们第一次的数据,因为校验问题没有成功入库,也要清理map,不清理会导致后面的数据都不能插入!!!!!!意思就是我们要在每一个自定义异常里清除map
我们定义一个全局 return方法,在方法里清除map
private String aj (boolean result, String reason,String key) {
if(result==false){
Map.remove(key);
}
JSONObject rsp = new JSONObject();
rsp.put("result", result);
rsp.put("reason", reason);
return rsp.toString();
}
例如:
} else {
return rsp(false, "身份证信息有误!!!",key);
}
刚工作没多久。。。请各位大佬指正,或者有没有更好的方法