You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala使用Mongo4cats连接MongoDB不生效且无异常抛出问题求助

问题根因

  1. IO 实例未被实际执行
    Cats Effect 的IO是惰性计算结构,仅构造IO实例不会触发任何实际的数据库操作、网络请求逻辑,你当前的代码只声明了操作流程,没有显式触发运行,所以无论连接串是否正确,程序都不会有实际动作也不会抛出异常。
  2. 连接串认证配置和本地 MongoDB 不匹配
    你本地通过mongo-shell可以无密码直接访问服务,说明本地 MongoDB 未开启身份认证,你的代码连接串中携带的root:secret账号不存在,就算逻辑运行也会出现认证失败。
  3. 密封类 ADT 编解码潜在问题
    PaymentMethod是密封 trait 结构,默认的 circe 自动推导可能无法正确处理多态序列化/反序列化,运行时容易抛出编解码错误。

解决方法

1. 替换主类继承关系,使用IOApp管理生命周期

Cats Effect 提供的IOApp会自动执行IO逻辑、管理程序生命周期,不需要手动调用unsafe方法,修改主类代码如下:

import cats.effect.{ExitCode, IO, IOApp, Resource}
import mongo4cats.client._
import io.circe.generic.auto._
import mongo4cats.bson.ObjectId
import mongo4cats.circe._

import java.time.Instant

// 替换原来的普通App为IOApp
object Main extends IOApp {
  val creditCard = CreditCard("John Bloggs", "1111222233334444", "1021", 919)
  val paypal = Paypal("hello.world@test.com")
  val payment1 = Payment(ObjectId(), BigDecimal(2.5), paypal, Instant.parse("2021-04-05T12:00:00Z"))
  val payment2 = Payment(ObjectId(), BigDecimal(9.99), creditCard, Instant.parse("2021-04-12T12:00:00Z"))

  // 本地未开认证去掉账号密码即可
  val mongoClient: Resource[IO, MongoClient[IO]] =
    MongoClient.fromConnectionString[IO]("mongodb://127.0.0.1:27017")

  // 实现IOApp要求的run方法
  override def run(args: List[String]): IO[ExitCode] = {
    mongoClient.use { client =>
      for {
        db <- client.getDatabase("testdb")
        coll <- db.getCollectionWithCodec[Payment]("payments")
        _ <- coll.insertOne(payment1)
        _ <- coll.insertMany(List(payment2))
        _ <- IO.println("数据插入完成")
      } yield ExitCode.Success
    }
  }
}

2. 修复密封类编解码

如果运行后出现PaymentMethod相关的序列化错误,在模型定义文件中补充显式的编解码配置即可:

import io.circe.{Codec, Decoder, Encoder}
import io.circe.generic.extras.Configuration
import mongo4cats.bson.ObjectId

import java.time.Instant

// 增加circe多态配置
implicit val circeConfig: Configuration = Configuration.default.withDiscriminator("paymentType")
sealed trait PaymentMethod
implicit val paymentMethodCodec: Codec[PaymentMethod] = io.circe.generic.extras.semiauto.deriveConfiguredCodec[PaymentMethod]

final case class Paypal(email: String) extends PaymentMethod

final case class CreditCard(
                             name: String,
                             number: String,
                             expiry: String,
                             cvv: Int
                           ) extends PaymentMethod

final case class Payment(
                          id: ObjectId,
                          amount: BigDecimal,
                          method: PaymentMethod,
                          date: Instant
                        )

内容的提问来源于stack exchange,提问作者sharingiscaring

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 13:39:04