首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Anorm和enum字段

Anorm和enum字段
EN

Stack Overflow用户
提问于 2012-01-23 23:19:44
回答 1查看 1.2K关注 0票数 2

我只是想知道如何在Anorm的case类中使用enum filed(类,从枚举扩展)。例如:

代码语言:javascript
复制
object Type extends Enumeration {
    type Type = Value
    val User, Admin = Value
}

case class User (
    id: Pk[Long],
    type: Type.Type
)

如果我尝试这样的代码,我得到"RuntimeException:类型models.User没有支持的构造函数“。我应该使用哪种DB字段类型来实现这些目的?我尝试过varchar,但没有成功。

EN

回答 1

Stack Overflow用户

发布于 2013-02-13 18:03:38

你可以通过反射来做到这一点。给定以下代码(Scala2.10),执行如下导入操作

代码语言:javascript
复制
import AnormEnumerationExtension.ToId._

并且您的枚举通过它的id持久化。如果你喜欢保存它的名字,使用

代码语言:javascript
复制
import AnormEnumerationExtension.ToName._

最后是EnumExtension:

代码语言:javascript
复制
import java.lang.reflect.InvocationTargetException
import scala.reflect.runtime.universe._

object AnormEnumerationExtension {      
  private lazy val rm = scala.reflect.runtime.currentMirror

  object ToId {
    implicit def enumToParameterValue[E <: Enumeration: TypeTag](enumValue: E#Value): ParameterValue[Int] = enumValue.id

    implicit def rowToEnumValue[E <: Enumeration: TypeTag]: Column[E#Value] = Column.nonNull { (value, meta) =>
      val MetaDataItem(qualified, _, _) = meta
      value match {
        case int: Int => {
          val methodSym = typeTag[E].tpe.member(newTermName("apply")).asMethod
          val im = rm.reflect(rm.reflectModule(typeOf[E].termSymbol.asModule).instance)
          try {
            Right(im.reflectMethod(methodSym)(int).asInstanceOf[E#Value])
          } catch {
            case e: InvocationTargetException if e.getCause.isInstanceOf[NoSuchElementException] =>
              Left(SqlMappingError(s"Can't convert $int to ${typeTag[E].tpe}, because it isn't a valid value: $qualified"))
          }
        }
        case _ => Left(TypeDoesNotMatch(s"Can't convert [$value:${value.asInstanceOf[AnyRef].getClass}] to ${typeTag[E].tpe}: $qualified"))
      }
    }
  }

  object ToName {
    implicit def enumToParameterValue[E <: Enumeration: TypeTag](enumValue: E#Value): ParameterValue[String] = enumValue.toString

    implicit def rowToEnumValue[E <: Enumeration: TypeTag]: Column[E#Value] = Column.nonNull { (value, meta) =>
      val MetaDataItem(qualified, _, _) = meta
      value match {
        case string: String => {
          val methodSym = typeTag[E].tpe.member(newTermName("withName")).asMethod
          val im = rm.reflect(rm.reflectModule(typeOf[E].termSymbol.asModule).instance)
          try {
            Right(im.reflectMethod(methodSym)(string).asInstanceOf[E#Value])
          }
          catch {
            case e: InvocationTargetException if e.getCause.isInstanceOf[NoSuchElementException] =>
              Left(SqlMappingError(s"Can't convert '$string' to ${typeTag[E].tpe}, because it isn't a valid value: $qualified"))
          }
        }
        case _ => Left(TypeDoesNotMatch(s"Can't convert [$value:${value.asInstanceOf[AnyRef].getClass}] to ${typeTag[E].tpe}: $qualified"))
      }
    }
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8973925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档