将Scala Anorm记录转换为特定对象

时间:2014-02-05 23:27:05

标签: scala playframework-2.0 anorm

使用findBy,如下所示,我可以在Authentications表中搜索keyvalue

的记录
def findBy(key: String, value: String): Any = DB.withConnection { implicit connection =>
  SQL("select * from authentications where {key}={value} limit 1").on('key -> key, 'value -> value)
}

示例:

Authentication.findByMe("email", "toot@toot.com")

返回:

res1: Any = SimpleSql(SqlQuery(select * from authentications where ?=? limit 1,List(key, value),None),List((key,ParameterValue(email,anorm.ToStatement$$anon$3@4ca9aed5)), (value,ParameterValue(toot@toot.com,anorm.ToStatement$$anon$3@18154945))),<function1>)

如何将其重新转换为身份验证对象?包含我从查询中返回的所有字段的对象。

我已经尝试了以下内容,但是当其中一列中存在null时,我无法传递可以为空的对象错误。我无法弄清楚如何使用提供的解决方案here

val authentication_parser =
  get[String]("email") ~
  get[String]("encrypted_password") ~
  get[String]("user_id") ~
  get[String]("token") ~
  get[Date]("created_at") ~
  get[Date]("updated_at")

val authentication = {
  authentication_parser map {
    case email~encrypted_password~user_id~token~created_at~updated_at => Authentication(email, encrypted_password, user_id, token, created_at, updated_at)
  }
}

像这样使用它:

def findBy(key: String, value: String): Any = DB.withConnection { implicit connection =>
  SQL("select * from authentications where {key}={value} limit 1").on('key -> key, 'value -> value).as(authentication *)
}

我也是Scala的新手,所以我遇到过像这样的问题。

1 个答案:

答案 0 :(得分:3)

您的表中可以为空的任何列都应该是Option对象中的Authentication。例如,如果你的表是这样的:

`email` varchar(255) NOT NULL,
`encrypted_password` varchar(255) NULL,
`user_id` int(11) NOT NULL,
`token` varchar(255) NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NULL

然后你应该:

case class Authentication(email: String, password: Option[String], userId: Int, token: Option[String], createdAt: Date, updatedAt: Option[Date])

您的解析器看起来像:

val authentication_parser = {
   get[String]("email") ~
   get[Option[String]]("encrypted_password") ~
   get[String]("user_id") ~
   get[Option[String]]("token") ~
   get[Date]("created_at") ~
   get[Option[Date]]("updated_at") map {
       case email~encrypted_password~user_id~token~created_at~updated_at => 
           Authentication(email, encrypted_password, user_id, token, created_at, updated_at)
   }
}

如果由于某种原因您不想在Option课程中使用Authentication,请在地图部分使用getOrElse并使用默认值填充(更加丑陋) :

case email~encrypted_password~user_id~token~created_at~updated_at => 
           Authentication(email, encrypted_password.getOrElse(""), user_id, token.getOrElse(""), created_at, updated_at.getOrElse(new Date())

对于偏执狂,您可能希望在从数据库中检索时从解析器中排除散列密码:

val authentication_parser = {
   get[String]("email") ~
   get[String]("user_id") ~
   get[Option[String]]("token") ~
   get[Date]("created_at") ~
   get[Option[Date]]("updated_at") map {
       case email~user_id~token~created_at~updated_at => 
           Authentication(email, None, user_id, token, created_at, updated_at)
   }
}

我还建议您更改.as()参数。 SQL("....").on(...).as(authentication_parser *)会解析为List[Authentication]。由于您在查询中使用LIMIT 1,因此最好使用authentication_parser.single(解析为Authentication)或authentication_parser.singleOpt(解析为Option[Authentication])。 singleOpt实际上是单个记录的方法,因为如果找不到任何内容,single将引发异常。

最后,你应该使你的函数的返回类型不是Any。 (无论与解析器匹配什么)抱歉文字墙。