由于现在在做的项目数据量太大,导致查询太慢,所以对查询出来的List<HashMap<String, Object>>类型的结果集进行了ehcache缓存处理,本来这样做是没什么问题的,但是当我们对缓存后的结果集进行相应的处理时,问题就发生了。
未加缓存处理前的代码:
List<HashMap<String, Object>> newWealths = indexService.newWealth(param); //查询结果集
for (HashMap<String, Object> newWealth: newWealths) {
String recommendStock = (String) newWealths.get("recommendStock");
recommendStock=stockCache.insertStockInfo(recommendStock,null); //对结果集的字段进行高亮处理(<a href="javascript:void(0);" style="color:red">recommendStock</a>)
newWealths.put("recommendStock", recommendStock);
}
model.put("list", newWealths); //添加到ModelMap对象中去
return "newwealth/newwealth"; //返回相应的jsp页面
很显然,当我们进行相应的处理后,结果集newWealths已经和从数据库里面读取出来的结果相较而言发生了改变,但引用地址仍然是相同的,在对recommendStock字段进行高亮处理后,newWealths对象的引用仍然是原来的newWealths对象引用,而当我们植入了缓存后,发起第二次发生请求时,缓存会拿到第一次运行的结果集的引用地址(即进行了高亮处理的newWealths对象),再次对该结果集进行高亮处理,从而导致仅有第一次访问的时候,结果集才是正确的。
解决:考虑到是由于高亮处理时在原来的结果集上进行处理而导致后续的问题,从而我们可以创建一个新的List<HashMap<String, Object>>集合来存储原来的newWealths对象,在新对象上进行高亮处理,这样就可以避免拿到缓存对象发生了变化(高亮处理)。
但是这里就有一个问题:由于list集合是引用传递,HashMap集合也是引用传递,当我们重新定义一个List<HashMap<String, Object>>类型的集合使用=或者addAll()来进行值的复制时,还是会修改原来的对象(因为=传递的是同一个引用地址,而使用addAll()拿到的list集合虽然是新的集合,但是集合内的引用对象HashMap还是原来的HashMap的引用地址,所以这二者导致的结果要么就是对原对象的引用处理,要么就是对原对象的引用元素的引用处理,至于采用clone()方法和new ArrayList<> (原对象)方法实际上实现的还是和addAll一样的,就不再解释)。
那么,讲讲我们该如何去解决这种问题,由于采用clone(),addAll(),new ArrayList<> (原对象)这三种方法都是会产生新对象,不会产生对同一个地址的引用,这个时候我们就可以通过for循环来将创建一个新的HashMap<String, Object>对象来获取原HashMap<String, Object>的值,将其存入我们新定义的List<HashMap<String, Object>>集合,这样就可以避免我们处理新的List<HashMap<String, Object>>集合对象时同时会对原对象产生更改。代码如下:
List<HashMap<String, Object>> newWealths = indexService.newWealth(param);
List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
for (HashMap<String, Object> hashMap : newWealths) {
HashMap<String, Object> newMap = (HashMap<String, Object>) hashMap.clone();
list.add(newMap);
}
for (HashMap<String, Object> l : list){
String recommendStock = (String) l.get("recommendStock");
recommendStock=stockCache.insertStockInfo(recommendStock,null);
l.put("recommendStock", recommendStock);
}
model.put("list", list);
return "newwealth/newwealth";