Минимизируйте код Boiler Plate при написании запросов 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)

Я хочу знать, есть ли общий и безопасный способ избежать повторного использования этих строк в каждой функции.


person Knows Not Much    schedule 19.07.2015    source источник


Ответы (1)


Вы можете определить общую функцию, например

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)
}
person Adi    schedule 19.07.2015
comment
Спасибо. это прекрасно работает. но я не понимаю DBIOAction[R, NoStream, Nothing]) Что такое NoStream? было бы неплохо, если бы вы также добавили некоторые пояснения к своему коду. - person Knows Not Much; 19.07.2015