Scala 光滑的左/右/外部连接,带选装件
在光滑的示例中,有几个连接示例,其中一个结果列可以为null,就像执行左、右或外连接时一样。例如:Scala 光滑的左/右/外部连接,带选装件,scala,slick,Scala,Slick,在光滑的示例中,有几个连接示例,其中一个结果列可以为null,就像执行左、右或外连接时一样。例如: val explicitLeftOuterJoin = for { (c, s) <- Coffees leftJoin Suppliers on (_.supID === _.id) } yield (c.name, s.name.?) val explicitLeftOuterJoin=for{ (c,s)更新:这将在2014年底解决,只需在Slick 3.0中工作即可,不再需要以
val explicitLeftOuterJoin = for {
(c, s) <- Coffees leftJoin Suppliers on (_.supID === _.id)
} yield (c.name, s.name.?)
val explicitLeftOuterJoin=for{
(c,s)更新:这将在2014年底解决,只需在Slick 3.0中工作即可,不再需要以下解决方法
这是目前Slick的一个限制。您必须对每一列单独调用。?。但是,您可以在表类中放置一个名为?
的函数,该函数将在中心位置执行此操作,从而获得完整的行。?。这包含一个涉及一些生成代码的通用解决方案。我们还提供了一个队列
从长远来看,我们将在Slick中支持一种外部联接的变体,其中Slick完全了解所涉及的类型,您无需指定。?任何地方。目前,我们必须使用涉及代码生成的变通方法。除上述答案外:
如果您有一个扩展表的类,并且您的*投影如下所示:
def * = (col1, col2, col3)
比您的?函数看起来更像:
def ? = (col1.?, col2.?, col3.?)
如果已定义此类函数,则可以编写:
for {
(x,y) <- x leftJoin y on (...)
} yield (x, y.?)
用于{
(x,y)不是最干净的解决方案(使用scalaz 7.0.6和shapeless 2.0.1),但这一解决方案目前有效(Slick 2.0.1):
使用上面的?
投影,可以创建一个平滑的投影来转换选项的元组值=>选项[TupleN]
=>选项[YourClass]
添加选项
投影
注意:序列
用于将选项
值的元组转换为选项[TupleN]
。序列
的代码定义在此答案底部
添加到供应商
。假设供应商
是案例类
import scalaz._, Scalaz._
import SequenceTupleOption._
def option = (id.?, name.?, street.?) <> (optionApply, optionUnapply)
def optionApply(t: (Option[Int], Option[String], Option[String])): Option[Comment] = {
sequence(t).map(Supplier.tupled)
}
def optionUnapply(oc: Option[Supplier]): Option[(Option[Int], Option[String], Option[String])] = None
高级:序列
,将选项
值的元组转换为选项[TupleN]
这是。序列
从选项
值的元组转换为选项[TupleN]
的困难部分(使用scalaz和shapeless)
序列
功能的高级概述(类型不正确):
将Option
的元组转换为不成形的HList[Option[\uz]]
序列
从HList[Option[\u]]]
到Option[HList[\u]]]
将HList
转换回元组
在Slick 3.1.1中,正确答案很简单(如一些评论中所述):
用于{
(c,s)与stackoverflow.com/questions/14990365/有关,您能给出一个关于table类的合适的?
实现的示例吗?看看Markus的下一个答案:def?=(col1.?,col2.?,col3.)
cvogt,Slick 2.2是否有任何更新?看起来下一个版本是3.02.2,已重命名为3.0。这将为s
生成一个Rep[选项[供应商]]
,而且无法使用。
for {
(x,y) <- x leftJoin y on (...)
} yield (x, y.?)
import scalaz._, Scalaz._
import SequenceTupleOption._
def option = (id.?, name.?, street.?) <> (optionApply, optionUnapply)
def optionApply(t: (Option[Int], Option[String], Option[String])): Option[Comment] = {
sequence(t).map(Supplier.tupled)
}
def optionUnapply(oc: Option[Supplier]): Option[(Option[Int], Option[String], Option[String])] = None
val explicitLeftOuterJoin = for {
(c, s) <- Coffees leftJoin Suppliers on (_.supID === _.id)
} yield (c, s.option)
import scalaz._, Scalaz._
import shapeless._, ops.hlist.{ RightFolder, Tupler }
object SequenceTupleOption {
object applicativeFolder extends Poly2 {
implicit def caseApplicative[A, B <: HList, F[_]](implicit
app: Applicative[F]
) = at[F[A], F[B]] {
(a, b) => app.ap(a)(app.map(b)(bb => (_: A) :: bb))
}
}
def sequence[T, EL <: HList, L <: HList, OL <: HList, OT](t: T)(implicit
gen: Generic.Aux[T, EL],
eq: EL =:= L,
folder: RightFolder.Aux[L, Option[HNil], applicativeFolder.type, Option[OL]],
tupler: Tupler.Aux[OL, OT]
): Option[OT] =
eq(gen.to(t)).foldRight(some(HNil: HNil))(applicativeFolder).map(tupler(_))
}
import scalaz._, Scalaz._
import SequenceTupleOption._
case class Person(id: Int, name: String, age: Int)
val t = (Option(1), Option("Bob"), Option(40))
val person: Option[Person] = sequence(t).map(Person.tupled) // Some(Person(1,Bob,40))
for {
(c, s) <- coffees joinLeft suppliers on (_.supID === _.id)
} yield (c, s)