【问题标题】:How to manage scala enum with Anorm?如何使用 Anorm 管理 scala 枚举?
【发布时间】:2014-06-13 20:34:29
【问题描述】:

我想通过使用枚举来创建用户角色(认为这是最好的主意)。

我应该如何处理这个?

我当前的代码如下所示:

object UserRole extends Enumeration {
  type UserRole = Value
  val admin, user, manager = Value
}    
case class User(id: Long, firstname: String, lastname: String, password: String, email: String, role: UserRole)

那么我应该如何定义用户“简单”:

val simple = {
    get[Long]("user.id") ~
      get[String]("user.firstname") ~
      get[String]("user.lastname") ~
      get[String]("user.password") ~
      get[String]("user.email") ~
      get[UserRole]("user.role")  map {
      case id~firstname~lastname~password~email~role => User(id, firstname, lastname, password, email, role)
    }
  }

我应该如何将它保存到数据库中?

CREATE TABLE user (
    id integer NOT NULL DEFAULT nextval('user_id_seq'),
    firstname varchar(60),
    lastname varchar(60),
    password varchar(255),
    email varchar(60),
    role varchar(40)
);

【问题讨论】:

    标签: scala enums anorm


    【解决方案1】:

    Anorm 不支持 scala 枚举(在我看来,scala 枚举非常糟糕)。我通常做的是用它自己的解析器和表空间创建另一个案例类,并将JOIN它用于相关查询。 UserRole 可以在 User 中进行解析,方法是将其组合在 User.simple 中。

    case class UserRole(id: Long, name: String)
    
    object UserRole {
        val simple: RowParser[UserRole] = {
            get[Long]("roles.id") ~
            get[String]("roles.name") map {
                case id~name => UserRole(id, name)
           }
        }
    }
    
    case class User(id: Long, firstname: String, lastname: String, password: String, email: String, role: UserRole)
    
    object User {
    
        val simple: RowParser[User] = {
            get[Long]("user.id") ~
            get[String]("user.firstname") ~
            get[String]("user.lastname") ~
            get[String]("user.password") ~
            get[String]("user.email") ~
            UserRole.simple map {
                case id~firstname~lastname~password~email~role => 
                    User(id, firstname, lastname, password, email, role)
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      作为另一种选择,您可以将角色建模为密封特征。

      sealed trait UserRole
      case object Admin extends UserRole
      case object User extends UserRole
      case object Manager extends UserRole
      

      然后为您的类型提供一个异常阅读器。

      implicit val column: Column[UserRole] = {
        Column.nonNull1 { (value, meta) =>
          val MetaDataItem(qualified, nullable, clazz) = meta
          value match {
            case "Admin" => Right(Admin)
            case "User" => Right(User)
            case "Manager" => Right(Manager)
            case unknown => Left(TypeDoesNotMatch(s"unknown UserRole from $unknown"))
          }
        }
      }
      

      然后您可以在行解析器中使用该类型,例如 get[UserRole]

      注意字符串上的匹配,这显然是一个不错的预算,但你明白了。

      有关更多详细信息,请参阅此处的文档,https://playframework.com/documentation/2.4.x/ScalaAnorm#Column-parsers

      【讨论】:

        猜你喜欢
        • 2012-06-19
        • 1970-01-01
        • 2012-07-15
        • 1970-01-01
        • 1970-01-01
        • 2014-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多