繁体   English   中英

带枚举值的Scala序列化异常

[英]Scala serialization exception with Enumeration Value

我正在使用scala的play 2.1框架和MongoDB Salat插件。

当我更新Enumeration.Value时,我得到一个例外:

java.lang.IllegalArgumentException: can't serialize class scala.Enumeration$Val
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270) ~[mongo-java-driver-2.11.1.jar:na]
    at org.bson.BasicBSONEncoder.putIterable(BasicBSONEncoder.java:295) ~[mongo-java-driver-2.11.1.jar:na]
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:234) ~[mongo-java-driver-2.11.1.jar:na]
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174) ~[mongo-java-driver-2.11.1.jar:na]
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120) ~[mongo-java-driver-2.11.1.jar:na]
    at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27) ~[mongo-java-driver-2.11.1.jar:na]

插入Enumeration.Value工作正常。 我的案例类看起来像:

case class User(
    @Key("_id") id: ObjectId = new ObjectId,
    username: String,
    email: String,
    @EnumAs language: Language.Value = Language.DE,
    balance: Double,
    added: Date = new Date)

和我的更新代码:

object UserDAO extends ModelCompanion[User, ObjectId] {

    val dao = new SalatDAO[User, ObjectId](collection = mongoCollection("users")) {}

    def update(): WriteResult = {
        UserDAO.dao.update(q = MongoDBObject("_id" -> new ObjectId(id)), o = MongoDBObject("$set" -> MongoDBObject("language" -> Language.EN))))
    }
}

有任何想法如何工作?

编辑:

解决方法:如果我将Enumeration.Value转换为toString,它会起作用,但这不是它应该如何...

UserDAO.dao.update(q = MongoDBObject("_id" -> new ObjectId(id)), o = MongoDBObject("$set" -> MongoDBObject("language" -> Language.EN.toString))))

可以为枚举添加BSON编码。 因此,转换以透明的方式完成。

这是代码

RegisterConversionHelpers()
  custom()
  def custom() {
    val transformer = new Transformer {

      def transform(o: AnyRef): AnyRef = o match {
        case e: Enumeration$Val => e.toString
        case _ => o
      }
    }
    BSON.addEncodingHook(classOf[Enumeration$Val], transformer)
  }
}

在撰写本文时,mongoDB并不适合使用scala枚举,我使用装饰器方法作为解决方法。

说你有这个枚举:

object EmployeeType extends Enumeration {
  type EmployeeType = Value
  val Manager, Worker = Value
}

这个mongodb记录:

import EmployeeType._
case class Employee(
  id: ObjectId = new ObjectId
)

在你的mongoDB中,存储枚举的整数索引而不是枚举本身:

case class Employee(
  id: ObjectId = new ObjectId,
  employeeTypeIndex: Integer = 0
){
  def employeeType = EmployeeType(employeeTypeIndex); /* getter */
  def employeeType_=(v : EmployeeType ) = { employeeTypeIndex= v.id} /* setter */
}

额外的方法为员工类型枚举实现getter和setter。

Salat仅在使用grater与模型对象进行序列化时才会工作,而不是在您自己使用MongoDB对象进行查询时。 mongo驱动程序api对注释@EnumAs一无所知。 (除此之外,即使你可以使用salat,它怎么能知道你在泛型键 - >值MongoDBObject中引用User.language?)

所以你必须像你在你的解决方法中描述的那样做。 当您想要查询时,自己提供枚举的“值”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM