Slick 3 insert not inserting but no error

时间:2015-07-31 20:03:06

标签: scala slick slick-3.0

I'm trying to get a hang of Slick by doing a small test. I'm trying to do an insert. The test runs, no errors, but when I check the db, no record has been inserted.

What am I doing wrong?

Here's my test code:

Note: I disabled the first 'flatMap' because when I wanted to test the second insert method, and that code was not executed when the first flatmap function was enabled.

Both insert methods do not insert a new record. The first query for all items does work. The 'Test id:xx' lines are printed to console.

object TestSlick extends App {

  import slick.driver.PostgresDriver.api._
  import concurrent.ExecutionContext.Implicits.global
  import concurrent.duration._

  val config = ConfigFactory.load()
  val username = config.getString("app.database.jdbc.username")
  val password = config.getString("app.database.jdbc.password")
  val url: String = config.getString("app.database.jdbc.url")

  val db = Database.forURL(url, username, password)

  try {
    import Tables._

    val res = db.run(headlines.result).map(_.foreach {
      case HeadLineRow(id, _, _, _, _, companyId, text, from, days, end, user) =>
        println(s"Test id:$id")
    }).flatMap { _ =>
//      println("Inserting....")
//      val ts = Timestamp.valueOf(LocalDateTime.now())
//      val insertAction: DBIO[Option[Int]] = (headlines returning headlines.map(_.id)) +=
//        HeadLineRow(None, 100, 100, "tekst", ts, 5, ts, None, None, None, None)
//
//      db.run(insertAction.transactionally.map(
//        newId => println(s"New id: $newId"))
//      )
//    }.flatMap { _ =>
      println("Inserting....(2)")
      val ts = Timestamp.valueOf(LocalDateTime.now())
      val insertAction = headlines.map(p => p) += HeadLineRow(None, 1921, 65, "tekst2", ts, 5, ts, None, None, None, None)

      db.run(insertAction.transactionally.map(
        r => println(s"Insert result: ${r}"))
      )
    }

    Await.ready(res, 30 seconds);

  } finally db.close()
}

And my table (generated using Slick's generator and then adjusted a bit (auto-inc id, swapped some properties around))

package com.wanneerwerkik.db.slick

// AUTO-GENERATED Slick data model
/** Stand-alone Slick data model for immediate use */
object Tables extends {
  val profile = slick.driver.PostgresDriver
} with Tables

/** Slick data model trait for extension, choice of backend or usage in the cake pattern. (Make sure to initialize this late.) */
trait Tables {
  val profile: slick.driver.JdbcProfile
  import profile.api._
  import slick.model.ForeignKeyAction
  import slick.collection.heterogeneous._
  import slick.collection.heterogeneous.syntax._
  // NOTE: GetResult mappers for plain SQL are only generated for tables where Slick knows how to map the types of all columns.
  import slick.jdbc.{GetResult => GR}

  /** DDL for all tables. Call .create to execute. */
  lazy val schema = Array(headlines.schema).reduceLeft(_ ++ _)
  @deprecated("Use .schema instead of .ddl", "3.0")
  def ddl = schema

  /**
   * Entity class storing rows of table 'head_line_bar'
   *  @param id Database column id SqlType(int4), PrimaryKey
   *  @param createdBy Database column created_by SqlType(int4), Default(None)
   *  @param createdOn Database column created_on SqlType(timestamp), Default(None)
   *  @param updatedBy Database column updated_by SqlType(int4), Default(None)
   *  @param updatedOn Database column updated_on SqlType(timestamp), Default(None)
   *  @param companyId Database column company_id SqlType(int4), Default(None)
   *  @param contentType Database column content_type SqlType(varchar), Length(255,true), Default(None)
   *  @param fromDate Database column from_date SqlType(timestamp), Default(None)
   *  @param numberofdays Database column numberofdays SqlType(int4), Default(None)
   *  @param uptoEndDate Database column upto_end_date SqlType(timestamp), Default(None)
   *  @param userId Database column user_id SqlType(int4), Default(None)
   */
  case class HeadLineRow(
      id: Option[Int],
      userId: Int,
      companyId: Int,
      contentType: String,
      fromDate: java.sql.Timestamp,
      numberofdays: Int,
      uptoEndDate: java.sql.Timestamp,
      createdBy: Option[Int] = None,
      createdOn: Option[java.sql.Timestamp] = None,
      updatedBy: Option[Int] = None,
      updatedOn: Option[java.sql.Timestamp] = None
  )

  /** GetResult implicit for fetching HeadLineBarRow objects using plain SQL queries */
  implicit def GetResultHeadLineRow(implicit e0: GR[Int], e1: GR[Option[Int]], e2: GR[Option[java.sql.Timestamp]], e3: GR[Option[String]]): GR[HeadLineRow] = GR{
    prs => import prs._
    HeadLineRow.tupled((<<?[Int], <<[Int], <<[Int], <<[String], <<[java.sql.Timestamp], <<[Int], <<[java.sql.Timestamp], <<?[Int], <<?[java.sql.Timestamp], <<?[Int], <<?[java.sql.Timestamp]))
  }
  /**
   * Table description of table head_line_bar.
   * Objects of this class serve as prototypes for rows in queries.
   */
  class Headlines(_tableTag: Tag) extends Table[HeadLineRow](_tableTag, "head_line_bar") {
    def * = (id, userId, companyId, contentType, fromDate, numberofdays, uptoEndDate, createdBy, createdOn, updatedBy, updatedOn) <> (HeadLineRow.tupled, HeadLineRow.unapply)
    /** Maps whole row to an option. Useful for outer joins. */
    def ? = (Rep.Some(id), userId, companyId, contentType, fromDate, numberofdays, uptoEndDate, createdBy, createdOn, updatedBy, updatedOn).shaped.<>({r=>import r._; _1.map(_=> HeadLineRow.tupled((_1.get, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11)))}, (_:Any) =>  throw new Exception("Inserting into ? projection not supported."))

    /** Database column id SqlType(int4), PrimaryKey */
    val id: Rep[Option[Int]] = column[Option[Int]]("id", O.PrimaryKey, O.AutoInc)
    /** Database column user_id SqlType(int4), Default(None) */
    val userId: Rep[Int] = column[Int]("user_id")
    /** Database column company_id SqlType(int4), Default(None) */
    val companyId: Rep[Int] = column[Int]("company_id")
    /** Database column content_type SqlType(varchar), Length(255,true), Default(None) */
    val contentType: Rep[String] = column[String]("content_type", O.Length(255,varying=true))
    /** Database column from_date SqlType(timestamp), Default(None) */
    val fromDate: Rep[java.sql.Timestamp] = column[java.sql.Timestamp]("from_date")
    /** Database column numberofdays SqlType(int4), Default(None) */
    val numberofdays: Rep[Int] = column[Int]("numberofdays")
    /** Database column upto_end_date SqlType(timestamp), Default(None) */
    val uptoEndDate: Rep[java.sql.Timestamp] = column[java.sql.Timestamp]("upto_end_date")
    /** Database column created_by SqlType(int4), Default(None) */
    val createdBy: Rep[Option[Int]] = column[Option[Int]]("created_by", O.Default(None))
    /** Database column created_on SqlType(timestamp), Default(None) */
    val createdOn: Rep[Option[java.sql.Timestamp]] = column[Option[java.sql.Timestamp]]("created_on", O.Default(None))
    /** Database column updated_by SqlType(int4), Default(None) */
    val updatedBy: Rep[Option[Int]] = column[Option[Int]]("updated_by", O.Default(None))
    /** Database column updated_on SqlType(timestamp), Default(None) */
    val updatedOn: Rep[Option[java.sql.Timestamp]] = column[Option[java.sql.Timestamp]]("updated_on", O.Default(None))
  }
  /** Collection-like TableQuery object for table HeadLineBar */
  lazy val headlines = new TableQuery(tag => new Headlines(tag))

}

Log output is too big to paste here so I put it in this gist.

As suggested I added a readLine to wait for the result, but it was already output the same stuff. I also added a completion handler on the Future to print it's Success or Failure. Apparently it fails with a RejectedExecutionException. Why?

Failure: java.util.concurrent.RejectedExecutionException: Task slick.backend.DatabaseComponent$DatabaseDef$$anon$2@2e4db0df rejected from java.util.concurrent.ThreadPoolExecutor@43760a50[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]

1 个答案:

答案 0 :(得分:0)

这只是猜测,但也许你的测试框架在某种程度上被flatMap内部产生新任务,再次需要执行上下文这一事实所困惑(参见例如this thread - 它&#39;关于Scala 2.10,但我认为这没有改变)。因此,在插入执行之前释放资源。

您是否尝试过将println放入finally块中,看看是否在插入消息之前或之后调用了它?

您是否尝试使用等待同步运行两个期货?在这种情况下,你可能不会遇到这个问题。

您可以考虑使用完全异步支持进行测试,请参阅例如this link