【问题标题】:Slick 3.1.1 insert element into database without AutoIncSlick 3.1.1 在没有 AutoInc 的情况下将元素插入数据库
【发布时间】:2016-09-08 19:15:24
【问题描述】:

我正在尝试将一个元素简单地插入数据库,而表上没有 autoinc 标志。

这是表定义,我已经定义了所有适当的映射器:

class BlockHeaderTable(tag: Tag) extends Table[BlockHeader](tag,"block_headers")  {

  def hash = column[DoubleSha256Digest]("hash", O.PrimaryKey)

  def version = column[UInt32]("version")

  def previousBlockHash = column[DoubleSha256Digest]("previous_block_hash")

  def merkleRootHash = column[DoubleSha256Digest]("merkle_root_hash")

  def time = column[UInt32]("time")

  def nBits = column[UInt32]("n_bits")

  def nonce = column[UInt32]("nonce")

  def * = (hash, version, previousBlockHash, merkleRootHash, time, nBits, nonce).<>[BlockHeader,
    (DoubleSha256Digest, UInt32, DoubleSha256Digest, DoubleSha256Digest, UInt32, UInt32, UInt32)](blockHeaderApply,blockHeaderUnapply)
}

我正在尝试为此表创建一个简单的插入函数。这是我的尝试:

  override val table = TableQuery[BlockHeaderTable]

  def create(blockHeader: BlockHeader): Future[BlockHeader] = {
    val insertAction = table += blockHeader
    database.run(insertAction)
  }

我收到以下类型的错误:

chris@chris-870Z5E-880Z5E-680Z5E:~/dev/bitcoins-spv-node$ sbt compile 
[info] Loading project definition from /home/chris/dev/bitcoins-spv-node/project
[info] Set current project to bitcoins-spv-node (in build file:/home/chris/dev/bitcoins-spv-node/)
[info] Compiling 1 Scala source to /home/chris/dev/bitcoins-spv-node/target/scala-2.11/classes...
[error] /home/chris/dev/bitcoins-spv-node/src/main/scala/org/bitcoins/spvnode/models/BlockHeaderDAO.scala:30: type mismatch;
[error]  found   : slick.profile.FixedSqlAction[Boolean,slick.dbio.NoStream,slick.dbio.Effect.Write]
[error]  required: slick.dbio.DBIOAction[org.bitcoins.core.protocol.blockchain.BlockHeader,slick.dbio.NoStream,Nothing]
[error]     database.run(insertAction)
[error]                  ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 3 s, completed Sep 8, 2016 2:11:32 PM

【问题讨论】:

  • 你在哪里定义你的 insertAction?看起来它不是从 DBIOAction 继承的?
  • table 只是一个TableQuery 对象,blockHeadertable 存储的对象的一个​​实例。 +=SimpleInsertActionComposer 内部定义
  • 我想主要问题是插入语句是否可以在DBIO.seq 之外使用,他们使用它的每个测试用例都使用该函数:github.com/slick/slick/blob/…
  • 对此不确定,但插入通常会返回插入的行数。如果要返回刚刚插入的对象,请尝试将table += blockHeader 更改为(table += blockHeader).andThen(DBIO.successful(blockHeader))
  • @Roman 这不会导致Future[BlockHeader]——必须有更好的方法来做到这一点

标签: scala slick


【解决方案1】:

默认情况下,+= 返回受影响的行数,通常为 1。但是,为了满足 create 函数的签名,您需要返回 BlockHeader。您可以通过简单地链接一个返回“插入”值的DBIO.successful() 操作来做到这一点:

def create(blockHeader: BlockHeader): Future[BlockHeader] = {
  val insertion: DBIO[BlockHeader] = (table += blockHeader).andThen(DBIO.successful(blockHeader))
  database.run(insertAction)
}

andThen 在第一个动作成功后立即执行,并将返回第二个动作的值。

不要与returning 混淆。使用returning,您可以更改+=++= 返回的值。也就是说,大多数 DBMS 只允许返回一个自动递增的主键。例如,如果 hash 是一个自动递增的值,您可以像这样返回它:

val hash = (table returning table.map(_.hash)) += blockHeader

更进一步,您还可以使用 into 将该值插入到您的 BlockHeaderobject 中:

val blockHeaderWithHash = (table returning table.map(_.hash) into ((blockHeader, hash) => blockHeader.copy(hash = hash))) += blockHeader

【讨论】:

    【解决方案2】:

    您的insertAction 返回插入的行数,因此您应该映射该值并检查操作是否成功:

    def create(blockHeader: BlockHeader): Future[BlockHeader] = {
      val insertAction = (table += blockHeader).flatMap {
        case 0 => DBIO.failed(new Exception("Failed to insert `BlockHeader` object"))
        case _ => DBIO.successful(blockHeader)
      }
    
      db.run(insertAction)
    }
    

    【讨论】:

      猜你喜欢
      • 2022-07-21
      • 2016-07-06
      • 1970-01-01
      • 2015-01-19
      • 1970-01-01
      • 1970-01-01
      • 2014-03-20
      • 1970-01-01
      • 2023-03-20
      相关资源
      最近更新 更多