【问题标题】:Turn Scala Anorm record into a specific object将 Scala Anorm 记录转换为特定对象
【发布时间】:2014-03-02 16:29:44
【问题描述】:

使用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>)

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

我尝试了以下方法,但是当其中一列中有空值时,我无法传递可空对象错误。我不知道如何使用提供的解决方案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 的新手,所以我经常遇到这样的问题。

【问题讨论】:

    标签: scala playframework-2.0 anorm


    【解决方案1】:

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

    `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)
       }
    }
    

    如果由于某种原因你不想在 Authentication 类中使用 Option,那么在地图部分使用 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。 (与解析器匹配的任何内容)对不起文字墙。

    【讨论】:

    • 希望我刚开始的时候有这个解释;)
    • 现在我在创建身份验证时遇到错误,类型不匹配,因为 Option[String] 与 String [error] found : String [error] required: Option[String] [error] val authentication = new Authentication(u.email, u.password.bcrypt, user.id, token , now, now) 不同,另外,惊人的答案
    • 仔细观察,我是否只需将我的Strings 初始化为Option[String]s?在那种情况下,我可能会使用getOrElse 方法
    • 按照我的例子,你需要new Authentication(u.email, Some(u.password.bcrypt), user.id, Some(token), now, (now))。要创建Option,您需要将其声明为NoneSome(value)
    • @ThomasPotaire getSqlParser 对象中。所以要么import anorm.SqlParser._要么使用SqlParser.get
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    相关资源
    最近更新 更多