如何定义空查询
How to define an empty query
在 for-comp
中,我需要设置一些查询,然后 运行 稍后在单次拍摄中......比如:
val queries = for {
_ <- query1
_ <- query2
id <- someInsertQuery
} yield id
db.run(queries.transactionally)
提示:查询是slick.jdbc.JdbcActionComponent#ProfileAction
的实例
现在,我需要为前两个查询设置条件。如果满足条件,查询应该 运行,否则没有。所以我想:
val queries = for {
_ <- if (condition1) query1 else Query.empty
_ <- if (condition2) query2 else Query.empty
id <- someInsertQuery
} yield id
db.run(queries.transactionally)
但这行不通:
value flatMap is not a member of Object
[error] _ <- if (condition1) query1 else Query.empty
[error] ^
所以我敢打赌我想做的不是这种方式。实现这一目标的正确方法是什么?
更新1:
更多细节。 for-comp 中的第一项如下所示(考虑 Boris 的想法):
val queries = for {
_ <- someOption.map(someRow => SomeTableQuery += someRow).geOrElse(Query.empty.result)
}
SomeTableQuery
是 slick.lifted.TableQuery[SomeClass]
的实例,someOption
是 Option[SomeClass]
到目前为止,我能够解决它的最好方法是在 filter
中获取条件。大致:
val queries = for {
_ <- query1.filter(condition1)
_ <- query2.filter(condition2)
id <- someInsertQuery
} yield id
db.run(queries.transactionally)
如果您有其他想法,请告诉我。
我认为您对 for-yield 构造有一些误解。
在scala中,for-yield只是一些flatMap
、map
函数组合下的语法糖。
val queries = for {
_ <- if (condition1) query1 else Query.empty
_ <- if (condition2) query2 else Query.empty
res <- someInsertQuery
} yield res
对于编译器,它等同于:
query1.flatMap(_ => query2.flatMap(_ => someInsertQuery.map(res => res)))
如果你的 query1
和 query2
是 ProfileAction
:
val query1: ProfileAction[Int, NoStream, Effect.Write] = ???
val query2: ProfileAction[Int, NoStream, Effect.Write] = ???
所以,表达式 if (condition1) query1 else Query.empty
的类型是 Object
,因为 Query.empty
的类型是 - Query[Unit, Unit, Seq]
和 Query
的最近共同祖先并且ProfileAction
是 Object
类型,没有 flatMap
功能。为了使您的代码可编译,您应该使 if ... else
构造的所有分支具有相同的类型并具有 flatMap
函数,如果我们在 Query.empty
上调用 result
就会这样:
val result1: FixedSqlAction[Any, NoStream, Effect.Write with Effect.Read] = if (condition1) query1 else Query.empty.result
val result2: FixedSqlAction[Any, NoStream, Effect.Write with Effect.Read] = if (condition2) query2 else Query.empty.result
您的代码的可能版本:
import slick.jdbc.JdbcBackend
import slick.lifted.Query
import slick.jdbc.H2Profile.api._
val db: JdbcBackend.Database = ???
val query1: ProfileAction[Int, NoStream, Effect.Write] = ???
val query2: ProfileAction[Int, NoStream, Effect.Write] = ???
val someInsertQuery: ProfileAction[Int, NoStream, Effect.Write] = ???
val condition1 = false
val condition2 = true
val queries = for {
_ <- if (condition1) query1 else Query.empty.result
_ <- if (condition2) query2 else Query.empty.result
res <- someInsertQuery
} yield res
db.run(queries.transactionally)
如果您的查询实际上是选项而不仅仅是查询,您可以使用 flatMap
编写选项组合来过滤空选项,并使用 seq
来顺序执行结果查询序列。例如,在 slick documentation 中使用 table:
import slick.jdbc.H2Profile.api._
case class Coffees(tag: Tag) extends Table[(String, Double)](tag, "COFFEES") {
def name = column[String]("COF_NAME")
def price = column[Double]("PRICE")
def * = (name, price)
}
val coffees: TableQuery[Coffees] = TableQuery[Coffees]
val maybeQuery1 = Option(("Colombian", 7.99))
val maybeQuery2 = Option(("Another name", 14.59))
val maybeQuery3 = Option(("Name", 4.39))
val queries = Seq(maybeQuery1, maybeQuery2, maybeQuery3).flatMap(_.map(someRow => coffees += someRow))
val db: Database = ???
db.run(DBIO.seq(queries:_*).transactionally)
在 for-comp
中,我需要设置一些查询,然后 运行 稍后在单次拍摄中......比如:
val queries = for {
_ <- query1
_ <- query2
id <- someInsertQuery
} yield id
db.run(queries.transactionally)
提示:查询是slick.jdbc.JdbcActionComponent#ProfileAction
现在,我需要为前两个查询设置条件。如果满足条件,查询应该 运行,否则没有。所以我想:
val queries = for {
_ <- if (condition1) query1 else Query.empty
_ <- if (condition2) query2 else Query.empty
id <- someInsertQuery
} yield id
db.run(queries.transactionally)
但这行不通:
value flatMap is not a member of Object
[error] _ <- if (condition1) query1 else Query.empty
[error] ^
所以我敢打赌我想做的不是这种方式。实现这一目标的正确方法是什么?
更新1: 更多细节。 for-comp 中的第一项如下所示(考虑 Boris 的想法):
val queries = for {
_ <- someOption.map(someRow => SomeTableQuery += someRow).geOrElse(Query.empty.result)
}
SomeTableQuery
是 slick.lifted.TableQuery[SomeClass]
的实例,someOption
是 Option[SomeClass]
到目前为止,我能够解决它的最好方法是在 filter
中获取条件。大致:
val queries = for {
_ <- query1.filter(condition1)
_ <- query2.filter(condition2)
id <- someInsertQuery
} yield id
db.run(queries.transactionally)
如果您有其他想法,请告诉我。
我认为您对 for-yield 构造有一些误解。
在scala中,for-yield只是一些flatMap
、map
函数组合下的语法糖。
val queries = for {
_ <- if (condition1) query1 else Query.empty
_ <- if (condition2) query2 else Query.empty
res <- someInsertQuery
} yield res
对于编译器,它等同于:
query1.flatMap(_ => query2.flatMap(_ => someInsertQuery.map(res => res)))
如果你的 query1
和 query2
是 ProfileAction
:
val query1: ProfileAction[Int, NoStream, Effect.Write] = ???
val query2: ProfileAction[Int, NoStream, Effect.Write] = ???
所以,表达式 if (condition1) query1 else Query.empty
的类型是 Object
,因为 Query.empty
的类型是 - Query[Unit, Unit, Seq]
和 Query
的最近共同祖先并且ProfileAction
是 Object
类型,没有 flatMap
功能。为了使您的代码可编译,您应该使 if ... else
构造的所有分支具有相同的类型并具有 flatMap
函数,如果我们在 Query.empty
上调用 result
就会这样:
val result1: FixedSqlAction[Any, NoStream, Effect.Write with Effect.Read] = if (condition1) query1 else Query.empty.result
val result2: FixedSqlAction[Any, NoStream, Effect.Write with Effect.Read] = if (condition2) query2 else Query.empty.result
您的代码的可能版本:
import slick.jdbc.JdbcBackend
import slick.lifted.Query
import slick.jdbc.H2Profile.api._
val db: JdbcBackend.Database = ???
val query1: ProfileAction[Int, NoStream, Effect.Write] = ???
val query2: ProfileAction[Int, NoStream, Effect.Write] = ???
val someInsertQuery: ProfileAction[Int, NoStream, Effect.Write] = ???
val condition1 = false
val condition2 = true
val queries = for {
_ <- if (condition1) query1 else Query.empty.result
_ <- if (condition2) query2 else Query.empty.result
res <- someInsertQuery
} yield res
db.run(queries.transactionally)
如果您的查询实际上是选项而不仅仅是查询,您可以使用 flatMap
编写选项组合来过滤空选项,并使用 seq
来顺序执行结果查询序列。例如,在 slick documentation 中使用 table:
import slick.jdbc.H2Profile.api._
case class Coffees(tag: Tag) extends Table[(String, Double)](tag, "COFFEES") {
def name = column[String]("COF_NAME")
def price = column[Double]("PRICE")
def * = (name, price)
}
val coffees: TableQuery[Coffees] = TableQuery[Coffees]
val maybeQuery1 = Option(("Colombian", 7.99))
val maybeQuery2 = Option(("Another name", 14.59))
val maybeQuery3 = Option(("Name", 4.39))
val queries = Seq(maybeQuery1, maybeQuery2, maybeQuery3).flatMap(_.map(someRow => coffees += someRow))
val db: Database = ???
db.run(DBIO.seq(queries:_*).transactionally)