设为首页 加入收藏

TOP

细谈Slick(6)- Projection:ProvenShape,强类型的Query结果类型(三)
2017-10-10 12:10:48 】 浏览:1681
Tags:细谈 Slick Projection ProvenShape 类型 Query 结果
Inf).foreach {row => 26 println(s"${row._1.get} ${row._2} ${row._4.getOrElse("")}, ${row._3}") 27 }

在这个例子的表结构定义里默认的Projection是个Tuple。造成的后果是返回的结果行不含字段名,只有字段位置。使用这样的行数据很容易错误对应,或者重复确认正确的列值会影响工作效率。如果返回的结果类型是Seq[Person]这样的话:Person是个带属性的对象如case class,那么我们就可以通过IDE提示的字段名称来选择字段了。上面提过返回结果类型可以通过ProvenShape来确定,如果能实现ProvenShape[A] => ProvenShape[B]这样的转换处理,那么我们就可以把返回结果行类型从Tuple变成有字段名的类型了:

 1   class Person(val id: Option[Int],  2  val name: String, val age: Int, val alias: Option[String])  3   def toPerson(t: (Option[Int],String,Int,Option[String])) = new Person (  4  t._1,t._2,t._3,t._4  5  )  6   def fromPerson(p: Person) = Some((p.id,p.name,p.age,p.alias))  7   class TupleMappedPerson(tag: Tag) extends Table[  8     Person](tag,"PERSON") {  9     def id = column[Int]("id",O.PrimaryKey,O.AutoInc) 10     def name = column[String]("name") 11     def age = column[Int]("age") 12     def alias = column[Option[String]]("alias") 13     def * = (id.?,name,age,alias) <> (toPerson,fromPerson) 14  } 15   val tupleMappedPerson = TableQuery[TupleMappedPerson] 16   
17   Await.result(db.run(tupleMappedPerson.result),Duration.Inf).foreach {row =>
18     println(s"${row.id.get} ${row.name} ${row.alias.getOrElse("")}, ${row.age}") 19   }

我们用<>函数进行了Tuple=>Person转换。注意toPerson和fromPerson这两个相互转换函数。如果Person是个case class,那么Person.tupled和Person.unapply就是它自备的转换函数,我们可以用case class来构建MappedProjection:

 1   case class Person(id: Option[Int]=None, name: String, age: Int, alias: Option[String])  2 
 3   class MappedTypePerson(tag: Tag) extends Table[Person](tag,"PERSON") {  4     def id = column[Int]("id",O.PrimaryKey,O.AutoInc)  5     def name = column[String]("name")  6     def age = column[Int]("age")  7     def alias = column[Option[String]]("alias")  8     def * = (id.?,name,age,alias) <> (Person.tupled,Person.unapply)  9  } 10   val mappedPeople = TableQuery[MappedTypePerson]

从上面两个例子里我们似乎可以得出ProvenShape[T]的T类型就是Table[T]的T,也就是返回结果行的类型了。我们可以用同样方式来进行HList与Person转换: 

 1   def hlistToPerson(hl: Option[Int]::String::Int::(Option[String])::HNil) =
 2     new Person(hl(0),hl(1),hl(2),hl(3))  3   def personToHList(p: Person) = Some(p.id::p.name::p.age::p.alias::HNil)  4   class HListPerson(tag: Tag) extends Table[Person](tag,"PERSON") {  5     def id = column[Int]("id",O.PrimaryKey,O.AutoInc)  6     def name = column[String]("name")  7     def age = column[Int]("age")  8     def alias = column[Option[String]]("alias")  9     def * = (id.?)::name::age::alias::HNil <> (hlistToPerson,personToHList) 10  } 11   val hlistPerson = TableQuery[HListPerson] 12   Await.result(db.run(hlistPerson.result),Duration.Inf).foreach {row =>
13     println(s"${row.id.get} ${row.name} ${row.alias.getOrElse("")}, ${row.age}") 14   }

同样,必须首先实现hlistToPerson和personToHList转换函数。现在Table的类型参数必须是Person。上面的Projection都是对Table默认Projection的示范。实际上我们可以针对每个Query来自定义Projection,如下:

1  case class YR(name: String, yr: Int) 2 
3   val qYear = for { 4     p <- hlistPerson 5   } yield ((p.name, p.age) <> (YR.tupled,YR.unapply)) 6 
7   Await.result(db.run(qYear.result),Duration.Inf).foreach {row =>
8     println(s"${row.name} ${row.yr}") 9   }

上面这个例子里我们构建了基

首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇play for scala 实现SessionFilte.. 下一篇函数式中的 currying

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目