现在我已经升级到Anorm 2.4,我真的很难摆脱弃用警告.我已经看了
How to handle null in Anorm,但它对我没有帮助.
我们举一个简单的例子:帐户数据库表:
> id(bigint not null)
> email_address(varchar not null)
> first_name(varchar)
> last_name(varchar)
我的Scala代码中可以有两个函数:getAccountOfId和getAccountsOfLastName.
> getAccountOfId返回0或1个帐户,因此选项[(Long,String,Option [String],Option [String])]使我们的示例保持简单
> getAccountsOfLastName返回一个帐户列表(可能大小为0),因此List [(Long,String,Option [String],String)]使我们的示例变得简单
这两个函数的部分代码:
def getAccountOfId(id: Long): Option[(Long, String, Option[String], Option[String])] = {
DB.withConnection { implicit c =>
val query = """select email_address, first_name, last_name
from account
where id = {id};"""
/* Rest of the code that I struggle with unless I use deprecated functions */
}
}
def getAccountsOfLastName(lastName: String): List[(Long, String, Option[String], String)] = {
DB.withConnection { implicit c =>
val query = """select id, email_address, first_name
from account
where last_name = {lastName};"""
/* Rest of the code that I struggle with unless I use deprecated functions */
}
}
我希望这两个函数中的“其余代码”基于Anorm’s Parser API.
最佳答案 不确定这是否有帮助,但使用Anorm 2.4,我有一个如下所示的案例类:
final case class Role(id: Int,
label: String,
roletype: Int,
lid: Option[Int],
aid: Option[Int],
created: DateTime,
modified: DateTime)
然后只有它的解析器组合器,它看起来像这样:
val roleOptionRowParser = int("id") ~ str("label") ~ int("roletype") ~ (int("lid")?) ~ (int("vid")?) ~ get[DateTime]("created") ~
get[DateTime]("modified") map {
case id~label~roletype~lid~vid~created~modified ⇒ Some(Role(id, label, roletype, lid, vid, created, modified))
case _ ⇒ None
}
所以你基本上只是解析使用?用于可选字段的组合器,然后根据从SQL结果行中提取的内容进行匹配.然后,您可以通过以下方式将此应用于查询:
SQL(s"""
| select * from $source
| where $clause
""".stripMargin).on(params : _*).as(rowParser.single).get
其中’rowParser’在这种情况下只是对最后一批代码中定义的roleOptionRowParser的引用.
如果从查询中返回多行(或者期望有多行),那么可以在将它们传递给’as’函数之前应用相同的组合器(例如?或*),如下所示:
SQL(s"""
| select * from $source
| where $clause
""".stripMargin).on(params : _*).as(rowParser *).flatten
要么
SQL(s"""
| select * from $source
| where $clause
""".stripMargin).on(params : _*).as(rowParser ?).flatten
啊 – 忘了提到最后的’flatten’是因为我的解析器在这个例子中返回一个Option [Role],这取决于返回的行中是否存在所有必要的列值(这一位):
case id~label~roletype~lid~vid~created~modified ⇒ Some(Role(id, label, roletype, lid, vid, created, modified))
因此,当返回多行时,我只是应用’flatten’来提升Option类型,这样我最终会得到一个实际的’Role’实例列表.
干杯,
HTH.