【问题标题】:Slick insert, type mismatch光滑插入,类型不匹配
【发布时间】:2017-03-08 23:53:00
【问题描述】:

我正在尝试使用 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)

我不太确定如何使用我已经编写的代码返回指定的类型。

我从这里调用我的架构:

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\"}"))
    )

}

【问题讨论】:

    标签: scala types slick


    【解决方案1】:

    为了让这个答案更简短,我将参考 DBIO[T],这是 Slick 中 DBIOAction[T, NoStream, Effect.All] 的别名

    为什么会出现编译错误

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

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

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

    怎么办

    你可以做一些事情来解决这个问题。

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

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

    插入的结果

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

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

    如果您愿意,也可以使用 for 理解:

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

    (不使用andThen,但结果相同)。

    但是,如果您想要作为结果的案例类......好吧,您创建案例类,因此您可以在上面的理解示例中yield 它。 Slick 还支持 returninginto 作为更改 += 表达式的返回类型的一种方式:它在 the reference manual 中进行了描述。

    【讨论】:

      猜你喜欢
      • 2015-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多