光滑的插入,类型不匹配

Slick insert, type mismatch

我正在尝试使用 Slick 将一些数据插入到我的数据库中。我已经成功地查询了数据库,但不太明白如何使用文档示例插入数据。

我已经到了错误的地步,我的 action 类型不正确,它抛出了错误

type mismatch;
 found   : slick.dbio.DBIOAction[Unit,slick.dbio.NoStream,slick.dbio.Effect.Write with slick.dbio.Effect.Schema]
 required: slick.dbio.DBIOAction[com.ojolabs.customer.avro.CustomerEvent,slick.dbio.NoStream,Nothing]
      db.run(action)

我不太确定如何使用我已经编写的代码 return 根据需要指定的类型。

我从这里调用我的模式:

trait CustomerEventsComponent {
  def customEventsManager: CustomerEvents.Async
}

trait DefaultCustomerEvents extends CustomerEventsComponent{
  self: DatabaseComponent with ExecutionContextComponent =>

  lazy val customEventsManager = new Async {
    override def create(phoneNumber: String, createdAt: DateTime): Future[CustomerEvent] = {

      val action = Schema.CustomerEvents.userAction

      //this is the line that throws the error
      db.run(action)

    }
  }

}

我正在这里创建动作

object Schema {
  class CustomerEvents(tag: Tag) extends Table[CustomerEvent](tag, "customer_events") {
    def id: Rep[UUID] = column[UUID]("id", O.PrimaryKey)
    def customerId: Rep[UUID] = column[UUID]("customer_id")
    def eventType: Rep[String] = column[String]("type")
    def createdAt: Rep[DateTime] = column[DateTime]("created_at")
    def version: Rep[Double] = column[Double]("version")
    def data: Rep[JsValue] = column[JsValue]("data")
    def metadata: Rep[JsValue] = column[JsValue]("metadata")

    def * = (id, customerId, eventType, createdAt, version, data, metadata) <> (CustomerEvent.tupled, CustomerEvent.unapply)

  }

  object CustomerEvents {
    val all = TableQuery[CustomerEvents]

      val userAction = DBIO.seq(
        all.schema.create,
        all += CustomerEvent(
          UUID.randomUUID(),
          UUID.randomUUID(),
          "hello",
          DateTime.now(),
          1.0,
          Json.toJson("{\"hello\" : \"its me\"}"),
          Json.toJson("{\"hello\" : \"its me\"}"))
    )

}

为了让这个答案更短一些,我将引用 DBIO[T],它是 Slick 中 DBIOAction[T, NoStream, Effect.All][ 的别名=40=]

为什么会出现编译错误

错误是说编译器需要一个 DBIO[CustomerEvent] 但找到了一个 DBIO[Unit]。它期望该类型,因为 create 被定义为 return a Future[CustomerEvent](因此 db.run 应该 return )。

但是,Schema.CustomerEvents.userAction 调用了 DBIO.seqseq 是一种组合操作并忽略结果的方法。 DBIO.seq的return类型是DBIO[Unit](参考:Scala Doc)。

这就是您看到错误的原因:代码正在使用一种会丢弃结果的方法组合操作。

怎么办

您可以为此做一些事情。

  1. 如果实在不想要插入的结果,把create的类型改成Future[Unit]

  2. 如果您确实想要非 Unit 结果,则需要切换到与 seq 不同的 "combinator"。在这种情况下,我建议使用 andThen,它结合了两个动作,并保留第二个动作的值。我稍后会解释...

插入的结果

+= 默认为 return 受影响的行数。如果这是您想要的,那将是 create 上的 Future[Int] 类型。

userAction 最终会变成:all.schema.create andThen (all += ...etc)

或者,如果您愿意,可以使用 for comprehension:

for {
  _            <- all.schema.create
  rowsAffected <- all += ...etc
} yield rowsAffected

(未使用 andThen 但结果相同)。

但是,如果您想要结果 class 的案例...好吧,您创建案例 class,这样您就可以 yield 它在上面的理解示例中. Slick 还支持 returninginto 作为更改 += 表达式的 return 类型的一种方式:它在 the reference manual.

中有描述