删除mongodb iteratior报错:java.lang.UnsupportedOperationException: Cursors do not support removal
错误信息
Caused by: java.lang.UnsupportedOperationException: Cursors do not support removal at com.mongodb.client.internal.MongoBatchCursorAdapter.remove(MongoBatchCursorAdapter.java:44) ~[mongodb-driver-sync-4.0.3.jar:na] at com.example.demo.service.MongoService.getHisUserInfo(MongoService.java:55) ~[classes/:na] at com.example.demo.MongoDbCommandLinner.run(MongoDbCommandLinner.java:21) ~[classes/:na] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE] ... 5 common frames omitted
代码demo
package com.example.demo.service; import java.util.HashMap; import java.util.Map; import org.bson.Document; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.stereotype.Service; import com.mongodb.BasicDBObject; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; @Service public class MongoService { @Autowired private MongoTemplate mongoTemplate; private MongoCollection<Document> getCollection() { MongoDatabase mongoDatabase = mongoTemplate.getMongoDbFactory().getMongoDatabase("mytest"); MongoCollection<Document> collection = mongoDatabase.getCollection("his_data"); return collection; } public Map<String, Object> getHisUserInfo(String name) { Map<String, Object> result = new HashMap<>(); MongoCollection<Document> collection = getCollection(); BasicDBObject filter = new BasicDBObject(); filter.append("name", name); BasicDBObject showCols = new BasicDBObject(); showCols.append("addr", 1).append("age", 1).append("_id", 0); FindIterable<Document> find = collection.find(filter).limit(1); MongoCursor<Document> iterator = find.iterator(); Document doc = null; while (iterator.hasNext()) { doc = iterator.next(); break; } if (doc != null) { result.put("name", name); result.put("addr", doc.get("addr")); result.put("age", doc.get("age")); } iterator.remove(); return result; } }
调用getHisUserInfo方法时,出现异常
测试List遍历删除
我们知道如果一个集合中的数据遍历获取后,就不再需要了,对于这种情况,边遍历边删除是一种比较好的处理方式,可以节省内存
public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("test 001"); list.add("test 002"); list.add("test 003"); System.out.println("before remove: " + list); Iterator<String> iterator = list.iterator(); while(iterator.hasNext()) { iterator.remove(); } System.out.println("after remove: " + list); }
运行结果
before remove: [test 001, test 002, test 003] Exception in thread "main" java.lang.IllegalStateException at java.util.ArrayList$Itr.remove(Unknown Source) at com.example.demo.CommonTest.main(CommonTest.java:18)
删除时出现了异常,之前每太注意过这种情况,查看remove方法api介绍
从这个异常情况的描述信息可知,在调用iterator的remove方法时,要先调用其next方法,否则就会发生这样的异常,再while循环中remove方法调用前调用下next,确实是可以正常删除,此处不再贴出来代码,其实我们如果要清空一个集合,肯定也不会用这种方式来清空,直接调用list的clear方法更好,如果要删除指定的元素,也会调用下next方法,判断其值后进行删除,所以一般也不会出现什么问题。
Mongodb迭代删除异常原因
从上述遍历删除从mongodb获取的数据可以看出,已经调用了next方法,但是还会出现异常,究其原因,是由于ArrayList重写了Iterator的remmove方法,从mongodb删除报错的异常信息看,
MongoBatchCursorAdapter中的remove方法抛出的异常,我们进入到该类,查看其remove方法,
mongodb不允许我们在取出元素的同时,对其做删除操作