Java操作MongoDB报错 java.lang.IllegalStateException: state should be: open

问题描述

  • 我在使用Spark整合MongoDB,涉及到了MongoDB Colletion中的文档删除与新建(也就是更新文档)时,出现了报错java.lang.IllegalStateException: state should be: open
  • 错误代码如下
 /**
     * 将数据保存到 MongoDB userId -> 1, recs -> 22:4.5|45:3.8
     *
     * @param userId      用户ID
     * @param streamRecs  流式的推荐结果
     * @param mongoConfig MongoDB 的配置
     */
    public static void saveRecListToMongoDB(int userId, Tuple2<Integer, Double>[] streamRecs, Properties mongoConfig) {
        log.info("准备将实时推荐列表保存到 MongoDB,入参为:userId={} streamRecs={}", userId, streamRecs);
        // 1.连接到 StreamRecList实时推荐列表
        MongoCollection<Document> streamRecListCollection = null;
        try (MongoClient mongoClient = MongoClients.create(mongoConfig.getProperty("mongo.uri"))) {
            streamRecListCollection = mongoClient
                    .getDatabase(mongoConfig.getProperty("mongo.db"))
                    .getCollection(mongoConfig.getProperty("mongo.collection"));
        }
        // 2.删除 Mongo collection 中已存在的记录
        log.info("删除 Mongo collection 中已存在的用户 userId={} 的实时推荐表", userId);
        // fixme java.lang.IllegalStateException: state should be: open
        streamRecListCollection.findOneAndDelete(Filters.eq("userId", userId));

        
        // 3.插入文档(即将用户实时推荐列表写入到MongoDB)
        List<Document> recList = Arrays.stream(streamRecs).map(rec ->
                new Document().append("movieId", rec._1).append("rating", rec._2)
        ).collect(Collectors.toList());

        Document doc = new Document("userId", userId).append("recs", recList);

        streamRecListCollection.insertOne(doc);
    }

分析原因与解决

  • 1)我在想,既然Java编译器在编译器没有报错,那就应该不存在受检异常
  • 2)查找网络资料后,分析问题应该是出现在MongoDB连接的问题上,因此我检查了我的配置文件,如下:
# Mongo相关配置
mongo.uri=mongodb://192.168.188.128:27017,192.168.188.129:27017,192.168.188.130:27017/recommend
mongo.db=recommend
  • 3)配置文件也正确,那我们没有思绪了
  • 4)又想到是因为MongoDB连接上的问题,我又看到了在代码中使用了 try-with-resource语法,我觉得是因为这个语法的原因,因此我将对MongoDB 的操作都包裹在了try-with-resource中,代码如下:
    public static void saveRecListToMongoDB(int userId, Tuple2<Integer, Double>[] streamRecs, Properties mongoConfig) {
        log.info("准备将实时推荐列表保存到 MongoDB,入参为:userId={} streamRecs={}", userId, streamRecs);
        // 1.连接到 StreamRecList实时推荐列表
        MongoCollection<Document> streamRecListCollection = null;
        try (MongoClient mongoClient = MongoClients.create(mongoConfig.getProperty("mongo.uri"))) {
            streamRecListCollection = mongoClient
                    .getDatabase(mongoConfig.getProperty("mongo.db"))
                    .getCollection(mongoConfig.getProperty("mongo.collection"));

            // 2.删除 Mongo collection 中已存在的记录
            log.info("删除 Mongo collection 中已存在的用户 userId={} 的实时推荐表", userId);
            // fixme java.lang.IllegalStateException: state should be: open
            streamRecListCollection.findOneAndDelete(Filters.eq("userId", userId));


            // 3.插入文档(即将用户实时推荐列表写入到MongoDB)
            List<Document> recList = Arrays.stream(streamRecs).map(rec ->
                    new Document().append("movieId", rec._1).append("rating", rec._2)
            ).collect(Collectors.toList());

            Document doc = new Document("userId", userId).append("recs", recList);

            streamRecListCollection.insertOne(doc);
        }
    }

至此,Bug成功解决了

Bug复现

  • 1)Bug代码如下:
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import org.bson.Document;

/**
 * 演示 fixme java.lang.IllegalStateException: state should be: open
 */
public class BugTest {
    public static void main(String[] args) {
        // 1.连接到 StreamRecList实时推荐列表
        MongoCollection<Document> collection = null;
        try (MongoClient mongoClient = MongoClients.create("mongodb://192.168.188.150:27017/testdb")) {
            collection = mongoClient
                    .getDatabase("testdb")
                    .getCollection("user");
        }
        // 2.删除 Mongo collection 中已存在的记录
        // fixme java.lang.IllegalStateException: state should be: open
        collection.findOneAndDelete(Filters.eq("userId", 1));
        
        // 3.插入文档(即将用户实时推荐列表写入到MongoDB)
        Document doc = new Document("userId", 2);

        collection.insertOne(doc);
    }
}

  • 2)报错堆栈信息如下:
Exception in thread "main" java.lang.IllegalStateException: state should be: open
	at com.mongodb.assertions.Assertions.isTrue(Assertions.java:72)
	at com.mongodb.internal.connection.BaseCluster.getDescription(BaseCluster.java:167)
	at com.mongodb.internal.connection.SingleServerCluster.getDescription(SingleServerCluster.java:41)
	at com.mongodb.client.internal.MongoClientDelegate.getConnectedClusterDescription(MongoClientDelegate.java:155)
	at com.mongodb.client.internal.MongoClientDelegate.createClientSession(MongoClientDelegate.java:105)
	at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.getClientSession(MongoClientDelegate.java:287)
	at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:211)
	at com.mongodb.client.internal.MongoCollectionImpl.executeFindOneAndDelete(MongoCollectionImpl.java:733)
	at com.mongodb.client.internal.MongoCollectionImpl.findOneAndDelete(MongoCollectionImpl.java:714)
	at com.mongodb.client.internal.MongoCollectionImpl.findOneAndDelete(MongoCollectionImpl.java:708)
	at com.clear.bug.BugTest.main(BugTest.java:23)
  • 3)将MongoDB相关操作放入try-with-resource即可成功运行
public class BugTest {
    public static void main(String[] args) {
        // 1.连接到 StreamRecList实时推荐列表
        MongoCollection<Document> collection = null;
        try (MongoClient mongoClient = MongoClients.create("mongodb://192.168.188.150:27017/testdb")) {
            collection = mongoClient
                    .getDatabase("testdb")
                    .getCollection("user");


            // 2.删除 Mongo collection 中已存在的记录
            collection.findOneAndDelete(Filters.eq("userId", 1));

            // 3.插入文档(即将用户实时推荐列表写入到MongoDB)
            Document doc = new Document("userId", 2);

            collection.insertOne(doc);
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值