mongo-java-driver运行正常但mongodb-driver-reactivestreams无法插入数据
问题根因
你的JVM主线程在异步插入操作执行完成前就直接退出了,导致未发送的数据库请求直接被销毁,所以文档没有插入成功。同步驱动的insertOne是阻塞方法,会等待插入操作完成后才继续往下执行,因此可以正常插入。
你提供的两种异步写法分别存在以下问题:
- 第一种带订阅逻辑的写法:订阅后插入操作在MongoDB驱动的后台IO线程执行,主线程没有等待操作完成就直接结束进程,插入请求还未发送到数据库进程就已终止
- 第二种写法:
mongodb-driver-reactivestreams的插入方法返回的是Publisher,属于懒执行组件,你没有调用subscribe方法订阅的情况下,不会触发任何实际的数据库操作。
解决方法
- 所有异步操作必须显式调用
subscribe订阅才能触发执行 - 单测/main方法执行的测试场景下,需要加锁等待异步操作完成后再退出主线程,参考修改后的代码:
import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; // ...省略其他代码 CountDownLatch latch = new CountDownLatch(1); MongoClient mongoClient1 = MongoClients.create(); MongoDatabase database = mongoClient1.getDatabase("nifi"); Document doc = new Document("name", "MongoDB") .append("type", "database") .append("count", 1) .append("info", new Document("x", 203).append("y", 102)); Publisher<Success> publisher = database.getCollection("log").insertOne(doc); publisher.subscribe(new Subscriber<Success>() { @Override public void onSubscribe(final Subscription s) { s.request(1); System.out.println("开始执行插入"); } @Override public void onNext(final Success success) { System.out.println("插入成功"); } @Override public void onError(final Throwable t) { System.out.println("插入报错:" + t.getMessage()); t.printStackTrace(); latch.countDown(); } @Override public void onComplete() { System.out.println("操作完成"); latch.countDown(); } }); // 主线程最多等待10秒,避免异常情况下无限阻塞 latch.await(10, TimeUnit.SECONDS); // 关闭客户端释放资源 mongoClient1.close();
如果是在Web服务、定时任务这类常驻进程的场景下使用,不需要加CountDownLatch等待逻辑,因为主线程不会主动退出,异步操作会在后台正常执行完成。
内容的提问来源于stack exchange,提问作者MHegde
相关产品推荐
相关产品推荐

