2017-11-09 1 views
0

私はプレイ2.6.6スカラ座2.12.3ツルツル3.0.0を使用しています。ネストされたケースクラスのリストのための滑らかな投影を作成するには?

入れ子になった場合のクラスがあった場合、私は、最初の場合クラス構造を以下た:

case class Device(id: Int, deviceUser: Option[DeviceUser] =None) 

case class DeviceUser(name: Option[String] = None) 

だから、私はデバイスクラスに対して次の投影を作成した:

class DevicesTable(tag: Tag) extends Table[Device](tag, "DEVICES") { 

    def id = column[Int]("ID", O.PrimaryKey) 

    def name = column[Option[String]]("NAME") 

    def deviceUser = name.<>[Option[DeviceUser]](
     { 
     (param: Option[String]) => { 
      param match { 
      case Some(name) => Some(DeviceUser(Some(name))) 
      case None => None 
      } 
     } 
     }, 
     { 
     (t: Option[DeviceUser]) => 
     { 
      t match { 
      case Some(user) => Some(user.name) 
      case None => None 
      } 
     } 
     } 
    ) 

    def * = (id, deviceUser).<>(Device.tupled, Device.unapply) 
    } 

上記設定しましたうまく動作します。私は上記の投影法を使ってデータを簡単に保存して取り出すことができました。 But now, my requirement has changed and I need to store list of nested case class。だから、クラス構造は、次のようになりました。オプション[一覧[DeviceUser]]:私はフィールドdeviceUserための投影を定義することができ、いくつかの方法が

case class Device(id: Int, deviceUser: Option[List[DeviceUser]] =None) 

case class DeviceUser(name: Option[String] = None) 

ありますか?

更新:私はnon-relationalアプローチの詳細を探しています。何体は、これまでのソリューションを提案していない、ので

+0

1つのデバイスが多くDeviceUserを含めることができます - あなたは1対多のDBレベルでの関係としてそれを表現しなければならない –

+0

はい、それは次のようになります関係する方法。しかし、ここでは「非リレーショナル」アプローチをもっと探しています。 – oblivion

+0

JSON/XMLにシリアル化し、BLOB列に保存します。 DALはそれを解析し、必要なタイプを作成する必要があります。クールなアイディアザッツ –

答えて

0

、私は私が今使っているアプローチを共有しています。それは動作しますが、もちろん最善の解決策ではありません。特に、Awaitの使用を避けたいと考えており、generic implicit parserを開発したいと考えています。

また、私は別のDeviceUsersTableを作成する必要がありました。

case class DeviceUser(id: Int,name: Option[String] = None) 

    class DeviceUserRepo @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) { 

     val dbConfig = dbConfigProvider.get[JdbcProfile] 
     val db = dbConfig.db 
     import dbConfig.profile.api._ 
     val DeviceUsers = TableQuery[DeviceUserTable] 

     private def _findById(id: Int): DBIO[Option[DeviceUser]] = 
     DeviceUsers.filter(_.id === id).result.headOption 

     def findById(id: Int): Future[Option[DeviceUser]] = 
     db.run(_findById(id)) 

     def all: Future[List[DeviceUser]] = 
     db.run(DeviceUsers.to[List].result) 

     def create(deviceUser: DeviceUser): Future[Int] = { 
     db.run(DeviceUsers returning DeviceUsers.map(_.id) += deviceUser) 
     } 

     class DeviceUserTable(tag: Tag) extends Table[DeviceUser](tag, "DEVICE_USERS") { 

     def id = column[Int]("ID", O.PrimaryKey) 
     def name = column[Option[String]]("NAME") 
     def * = (id, name).<>(DeviceUser.tupled, DeviceUser.unapply) 
     } 

    } 

、元DevicesTableは次のようになります。

class DevicesTable(tag: Tag) extends Table[Device](tag, "DEVICES") { 

    implicit val deviceUserConverter = MappedColumnType.base[Option[List[DeviceUser]], String](
     deviceUsersOpt => { 
     deviceUsersOpt match { 
      case Some(users:List[DeviceUser]) =>val listOfId = users.map{ 
      k => val res = deviceUserRepo.create(k) 
       Await.result(res, 10 seconds) 
      } 
      listOfId.mkString(",") 
      case None => "" 
     } 
     }, 
     str =>{ 
     val listOfIds = (str split "," map Integer.parseInt).toList.filterNot(k => k.equals("")) 
     if(listOfIds.nonEmpty){ 
      val users = listOfIds.map{ k => 
      val res = deviceUserRepo.findById(k) 
      Await.result(res, 10 seconds) 
      } 
      Some(users.flatten) 
     } else { 
      None 
     } 
     } 
    ) 

    def id = column[Int]("ID", O.PrimaryKey) 

    def deviceUser = column[Option[List[DeviceUser]]]("DEVICE_USERS") 

    def * = (id, deviceUser).<>(Device.tupled, Device.unapply) 
    } 
関連する問題