如何在Play框架2.0中使用Scala重用Anorm解析器?

6
我一直在查看computer-database示例,我注意到为了重用Computer解析器,list方法使用了Computer.withCompany解析器,它返回一个(Computer, Company)元组。
在我处理的情况下,我不想使用计算机ID的引用,而是想要一个Computer对象,就像这样:
case class Computer(id: Pk[Long] = NotAssigned, name: String, introduced: Option[Date], discontinued: Option[Date], company: Company)
所以我在思考如何实现类似以下的代码(当然这只是伪代码)。
val simple = {
  get[Pk[Long]]("computer.id") ~
  get[String]("computer.name") ~
  get[Option[Date]]("computer.introduced") ~
  get[Option[Date]]("computer.discontinued") ~
  get[Company]("company.*") map {
    case id~name~introduced~discontinued~company => Computer(id, name, introduced, discontinued, company)
  }
}

显然,难点在于如何解决getCompany的问题。
有什么想法吗?
1个回答

5

我有一个Idea实体和一个IdeaType实体(就像计算机和公司,在计算机数据库示例中)。

case class IdeaTest(
  val id: Pk[Long]          = NotAssigned,
  val name: String          = "unknown idea",
  val description: String   = "no description",
  val kind: IdeaType        = IdeaType()
)

case class IdeaType (
  val id: Pk[Long] = NotAssigned,
  val name: String = "unknown idea type",
  val description: String = "no description"
)

我定义了一个TypeParser。
val typeParser: RowParser[IdeaType] = {
  get[Pk[Long]]("idea_type.id") ~
  get[String]("idea_type.name") ~
  get[String]("idea_type.description") map {
    case id~name~description => IdeaType(
      id, name, description
    )
  }
}

我尝试的第一件事是:

val ideaParser: RowParser[IdeaTest] = {
  get[Pk[Long]]("idea.id") ~
  get[String]("idea.name") ~
  get[String]("idea.description") ~
  typeParser map {
    case id~name~description~ideaType => IdeaTest(
      id, name, description, ideaType
    )
  }
}

尽管它编译成功了,但它总是有麻烦加载ideaType。

最终,我不得不定义一个没有ideaType的ideaParser,并与typeParser组合起来:

val typeParser: RowParser[IdeaType] = {
  get[Pk[Long]]("idea_type.id") ~
  get[String]("idea_type.name") ~
  get[String]("idea_type.description") map {
    case id~name~description => IdeaType(
      id, name, description
    )
  }
}

val ideaWithTypeParser = ideaParser ~ typeParser map {
  case idea~kind => (idea.copy(kind=kind))
}

以下是使用它的代码:

def ideaById(id: Long): Option[IdeaTest] = {
  DB.withConnection { implicit connection =>
    SQL("""
      select * from
      idea inner join idea_type 
      on idea.idea_type_id = idea_type.id 
      where idea.id = {id}""").
      on('id -> id).
      as(ideaParser.singleOpt)
  }
}

唯一的问题是我需要创建一个不一致状态(没有IdeaType)的IdeaTest对象,然后将其复制到另一个具有正确IdeaType的实例中。


1
这个回答非常有用,帮助我巩固了对于编写解析器的理解,谢谢! - EdgeCaseBerg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接