我正在使用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))))
答案 0 :(得分:5)
可以为Enumeration添加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)
}
}
答案 1 :(得分:3)
在撰写本文时,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。
答案 2 :(得分:1)
当您使用grater对模型对象进行序列化时,Salat只会执行其工作,而不是在您自己使用MongoDB对象进行查询时。 mongo驱动程序api对注释@EnumAs一无所知。 (除此之外,即使您可以使用salat,如何知道您在通用键 - >值MongoDBObject中引用User.language?)
所以你必须像你在你的解决方法中所描述的那样做。当你想进行查询时,自己提供枚举的“价值”。