2016-10-19 26 views
1

我對scala和浮油很新穎。我無法從此功能獲取聯繫人序列。每個聯繫人對象將具有名字,姓氏和一系列電話號碼。姓名和電話號碼使用外鍵存儲在相應的表格中。Scala/Slick:如何查詢表格並返回自定義對象的序列

def testContacts: Future[Seq[Contact]] = { 
    names.result.map { namelist => 
     var contacts = Seq[Contact]() 
     for (n <- namelist) {    
     println("NAME: " + n) // THIS IS PRINTED! 
     val phoneNumbers = for { 
      p <- phones.filter(_.nameId === n.id) 
     } yield p.phoneNumber 
     phoneNumbers.result.map { plist => 
      contacts = contacts :+ Contact(n.firstName, n.lastName, plist) 
      // Q: HOW DO I RETURN "contacts" to the caller? 
      println("CONTACTS: " + plist) // THIS IS **NOT** PRINTED! 
     } 
     } 
    } 
    Future { Seq[Contact]() } // dummy statement to avoid compilation error 
    } 

從控制檯:

階> Await.result(db.run(names.result),1000毫秒) 器Res9:序號[Example.NameTable#TableElementType] =矢量(名稱(喬治, W,1),名稱(約翰,A,2))

階> Await.result(db.run(phones.result),1000毫秒) res10:序號[Example.PhoneTable#TableElementType] =矢量(電話(+1 301 531 1121,1,1),電話(+1 301 748 5192,1,2),電話(+1 301 531 4519,2,3),電話(+1 202 667 9612,2,4) ),電話(+1 202 667 4044,2,5))

階> Await.result(testContacts,1000毫秒) res5:序號[Contacts.Contact] =列表()

階>

任何幫助理解。下面是完整的源代碼:

import scala.concurrent.Await 
import scala.concurrent.duration._ 
import scala.concurrent.ExecutionContext.Implicits.global 
import slick.driver.H2Driver.api._ 
import scala.util.Try 
import scala.concurrent.Future 

object Contacts extends App { 

    val db = Database.forConfig("dbconfig") 

    case class Contact(firstName: String, lastName: String, phones: Seq[String]) 

    def testContacts: Future[Seq[Contact]] = { 

    names.result.map { namelist => 
     var contacts = Seq[Contact]() 
     for (n <- namelist) { 
     println("NAME: " + n) 
     val phoneNumbers = for { 
      p <- phones.filter(_.nameId === n.id) 
     } yield p.phoneNumber 
     phoneNumbers.result.map { plist => 
      contacts = contacts :+ Contact(n.firstName, n.lastName, plist) 
      // Q: HOW DO I RETURN "contacts" to the caller? 
      println("CONTACTS: " + plist) // THIS IS NOT PRINTED! 
     } 
     } 
    } 
    Future { Seq[Contact]() } // dummy statement to avoid compilation error 
    } 

    case class Name(firstName: String, lastName: String, id: Long = 0L) 

    class NameTable(tag: Tag) extends Table[Name](tag, "Names") { 

    def id = column[Long]("ID", O.PrimaryKey, O.AutoInc) 
    def firstName = column[String]("FIRSTNAME") 
    def lastName = column[String]("LASTNAME") 

    override def * = (firstName, lastName, id) <> (Name.tupled, Name.unapply) 
    } 

    lazy val names = TableQuery[NameTable] 

    case class Phone(phoneNumber: String, nameId: Long, id: Long = 0L) 

    class PhoneTable(tag: Tag) extends Table[Phone](tag, "Phones") { 

    def id = column[Long]("ID", O.PrimaryKey, O.AutoInc) 
    def phoneNumber = column[String]("PHONE_NUMBER") 
    def nameId = column[Long]("NAME") 

    override def * = (phoneNumber, nameId, id) <> (Phone.tupled, Phone.unapply) 

    def name_fk = foreignKey("Phones_Names_ID_FK", nameId, names)(_.id, onUpdate = ForeignKeyAction.Cascade, onDelete = ForeignKeyAction.Cascade) 
    } 

    lazy val phones = TableQuery[PhoneTable] 

    def testNames = Seq(
    Name("George", "W"), 
    Name("John", "A")) 

    def testPhones = Seq(
    Phone("+1 301 531 1121", 1L), 
    Phone("+1 301 748 5192", 1L), 
    Phone("+1 301 531 4519", 2L), 
    Phone("+1 202 667 9612", 2L), 
    Phone("+1 202 667 4044", 2L)) 

    def populate: DBIOAction[Option[Int], NoStream,Effect.All] = { 
    for {  
     _ <- names.schema.drop.asTry andThen names.schema.create 
     _ <- phones.schema.drop.asTry andThen phones.schema.create 
     nameCount <- names ++= testNames 
     phoneCount <- phones ++= testPhones 
    } yield nameCount 
    } 
} 

回答

2

你testContacts查詢也不是很簡單的,我會用一個連接或在查詢語句中的過濾器,然後展開行

這裏是我會嘗試

def testContacts: Future[Seq[Contact]] = { 
    val query = for { 
    (n, pl) <- names join phones on (_.id === _.nameId) 
    } yield (n, pl) 
    db.run(query.result).map { (row) => 
    row.groupBy(_._1).map { r => 
     val name = r._1 
     val phones = r._2.map(_._2.phoneNumber) 
     Contact(name.firstName, name.lastName, phones) 
    }.toSeq 
    } 
} 

這裏使用了光滑的forcomp連接語法,然後

+0

感謝映射在結果這麼多!我能夠得到理想的結果。然而,當我嘗試調用從斯卡拉控制檯功能「testContacts」我得到錯誤「斯卡拉> testContacts 顯示java.lang.NullPointerException 在示例$ .testContacts(main.scala:312) ... 43省略掉 如果我手動輸入val query = ..和db.run語句,我可以正確地獲得聯繫人序列。任何想法?第312行指向db.run [對於混亂評論的歉意,無法輸入新行] – srvy

+0

我不知道不知道具體的,我有一個類似的NPE從控制檯運行,你可以發佈你的新代碼文件,這樣我可以匹配你的例子 – Selecsosi

+0

異常行可能是一個好主意,與NPE – Selecsosi

相關問題