编写Slick 3.0查询时最小化Boiler Plate代码

时间:2015-07-19 05:52:38

标签: scala slick slick-3.0

我在slick 3.0中编写了我的第一个数据访问对象。它有效,但我在代码中发现了很多重复的代码

class Items(tag: Tag) extends Table[Item](tag, "ITEMS") {
  def id = column[Long]("ITEMS_ID", O.PrimaryKey, O.AutoInc)
  def name = column[String]("ITEMS_NAME")
  def price = column[Double]("ITEMS_PRICE")
  def * = (id, name, price) <> ((Item.apply _).tupled, Item.unapply _)
}

object Shop extends Shop{
  val items = TableQuery[Items]
  val db = Database.forConfig("h2mem1")

  def create(name: String, price: Double) : Int = {
    val action = items ++= Seq(Item(0, name, price))
    val future1 = db.run(action)
    val future2 = future1 map {result => 
      result map {x => x}
    }
    Await.result(future2, Duration.Inf).getOrElse(0)
  }

  def list() : Seq[Item] = {
    val action = items.result
    val future = db.run(action)
    val future2 = future map {result => 
      result map {x => x}
    }
    Await.result(future2, Duration.Inf)
  }

  def get(id: Long) : Option[Item] = {
    val query = items.filter(_.id === id).result
    val future1 = db.run(query)
    val future2 = future1 map {result =>
      result.map {x => x}
    }
    Await.result(future2, Duration.Inf).headOption
  }

  def delete(id: Long) : Int = {
    val query = items.filter(_.id === id).delete
    val future1 = db.run(query)
    val future2 = future1 map {result =>
      result
    }
    Await.result(future2, Duration.Inf)
  }

  def update(item: Item) : Int = {
    val query = items.filter(_.id === item.id).update(item)
    val future1 = db.run(query)
    val future2 = future1 map {result => result}
    Await.result(future2, Duration.Inf)
  }

  def createItemsTable() : Boolean = {
    if (!checkTable("ITEMS")) {
      val action = items.schema.create
      val future1 = db.run(action)
      future1 map {x => x}
      true
    } else false
    //Await.result(future2, Duration.Inf)
  }

  def checkTable(tableName: String) : Boolean = {
    val action = MTable.getTables
    val future1 = db.run(action)
    val future2 = future1 map {result =>
      result map {x => x.name.name}
    }
    val retVal = Await.result(future2, Duration.Inf)
    retVal.exists(x => x == tableName)
  }
}

这有效,但我讨厌我一次又一次地编写这段代码的事实

val future1 = db.run(query)
val future2 = future1 map {result => result}
Await.result(future2, Duration.Inf)

val future1 = db.run(query)
val future2 = future1 map {result =>
    result.map {x => x}
}
Await.result(future2, Duration.Inf)

我想知道是否有一种通用且安全的方法可以避免在每个函数中重复使用这些行。

1 个答案:

答案 0 :(得分:2)

您可以定义类似

的通用函数
def runAction[R, Q](action: DBIOAction[R, NoStream, Nothing])(f: R => Q): Q = {
  val future1 = db.run(action)
  val future2 = future1 map { r: R =>
    f(r)
  }

  Await.result(future2, Duration.Inf)
}

并像

一样使用它
def create(name: String, price: Double): Int = {
  val action = items ++= Seq(Item(0, name, price))
  runAction(action)(_.map(x => x)).getOrElse(0)
}