我正在使用案例类在我们的应用程序中定义不同的“模型”数据。原因是能够轻松使用Jerkson(Scala界面到Jackson)。要将我的User
转换为Riak中的域对象,我在guid上使用了@RiakKey
注释。我有以下内容:
case class User(
@RiakKey val guid: String,
@RiakIndex(name = "email") val email: String,
val salt: String,
val passwordHash: String,
val emailHash: String,
val firstName: String,
val lastName: String,
val suspended: Boolean=false,
val created: Timestamp=now
)
当我在案例类上执行域转换时,无法识别@RiakKey
。它抛出一个NoKeySpecifedException
。这是我的转换器:
class UserConverter(val bucket: String) extends Converter[User] {
def fromDomain(domainObject: User, vclock: VClock) = {
val key = getKey(domainObject)
if(key == null) throw new NoKeySpecifedException(domainObject)
val kryo = new Kryo()
kryo.register(classOf[User])
val ob = new ObjectBuffer(kryo)
val value = ob.writeObject(domainObject)
RiakObjectBuilder.newBuilder(bucket, key)
.withValue(value)
.withVClock(vclock)
.withContentType(Constants.CTYPE_OCTET_STREAM)
.build()
}
}
这是Scala中带Java注释的问题吗?有解决方法吗?
这是创建和存储User对象的位置,以及引用转换器的位置:
1)
val user = parse[User](body) // jerkson parse, body is a string of JSON
User.store(user)
2)
object User {
val bucketName = "accounts-users"
val bucket = DB.client.createBucket(bucketName).execute()
def fetch(id: String) = bucket.fetch(id).execute().getValueAsString()
def store(o: User) = bucket.store( o ).withConverter(new UserConverter(bucketName)).execute()
}
Strack Trace
com.basho.riak.client.convert.NoKeySpecifedException
at com.basho.riak.client.bucket.DefaultBucket.store(DefaultBucket.java:455)
at com.threetierlogic.AccountService.models.User$.store(User.scala:58)
at com.threetierlogic.AccountService.controllers.Users$$anonfun$routes$3.apply(Users.scala:54)
at com.threetierlogic.AccountService.controllers.Users$$anonfun$routes$3.apply(Users.scala:51)
答案 0 :(得分:2)
(对于这个回答之前的漫长谈话,我道歉)
在学习了更多关于scala之后,我发现使用案例类你必须做一点不同。
http://piotrbuda.eu/2012/10/scala-case-classes-and-annotations-part-1.html
如果你这样做:
@(RiakKey@field) guid: String
它有效。
我在scala中编写了一个小型测试程序,并且能够使用getKey()
中使用的静态DefaultBucket
方法提取带注释的密钥,该方法返回null并导致抛出异常。
import com.basho.riak.client.convert.KeyUtil.getKey;
object Main {
def main(args: Array[String]): Unit = {
val u = User("my_key")
val k = getKey(u)
System.out.println(k);
}
}
User.scala
/* scala 2.9.1 would be scala.annotation.target.field */
import scala.annotation.meta.field
import com.basho.riak.client.convert.RiakKey;
case class User (@(RiakKey@field) guid: String)
输出:
my_key
(并且,如果您将注释更改回原来的方式,它会按预期返回null
)
答案 1 :(得分:0)
这是我提出的问题解决方法。我只是使用DefaultBucket.store
方法并手动指定密钥,而不是依赖注释。
我的用户随播广告对象:
object User {
val bucketName = "accounts-users"
val bucket = DB.client.createBucket(bucketName).execute()
def store(key: String, o: User) = bucket.store(key, o).withConverter(new UserConverter(bucketName)).execute()
}
使用它:
val user = parse[User](body)
User.store(user.guid, user)