尝试将我的项目从play 2.2.7迁移到2.3.8。
该项目包含以下代码:
def setCoordinatesOfAddresses(cardId: Long, caller: Option[Tuple2[Float,Float]] = None, event: Option[Tuple2[Float,Float]] = None) {
Logger.debug("callling SC.setCoordinatesOfAddresses")
DB.withConnection { implicit c =>
try {
val query = SQL("Execute Sc.setCoordinatesOfAddresses {cardId}, {deviceLatitude}, {deviceLongitude}, NULL, NULL, {eventsLatitude}, {eventsLongitude}")
query.on(
"cardId" -> cardId,
"deviceLatitude" -> caller.map(_._1).getOrElse(null),
"deviceLongitude" -> caller.map(_._2).getOrElse(null),
"eventsLatitude" -> event.map(_._1).getOrElse(null),
"eventsLongitude" -> event.map(_._2).getOrElse(null) ).execute()
} catch {
case e: Throwable => Logger.error("error", e)
}
}
Logger.debug("SC.setCoordinatesOfAddresses called")
}
编译器给了我这个错误:
Error:(384, 28) Play 2 Compiler:
../app/controllers/Cards.scala:384: No implicit view available from Any => anorm.ParameterValue.
"deviceLatitude" -> caller.map(_._1).getOrElse(null),
^
我该怎么做才能解决这个问题? 据我从文档中了解,我需要定义参数类型。但在下面的代码中,我无法理解在哪里以及如何做到这一点。
答案 0 :(得分:1)
尝试
val ps = Seq[anorm.ParameterValue](yourParameter1,yourParameter2) // Seq[ParameterValue]
SQL("SELECT * FROM test WHERE a={a} b={b}").
on('a -> ps(0), 'b -> ps(1))
您使用的是Any
(或其他)类型的参数,但文档说要使用anorm.ParameterValue
类型
答案 1 :(得分:1)
我建议先试试val p: ParameterValue = caller
。
我认为问题更多的是Tuple2[Float,Float]
(btw (Float, Float)
)没有特定的参数转换。
在Anorm 2.3之前,不安全的转换使用了.toString
(这会导致很多问题)。
更好的方法是将元组转换为格式化字符串,方法是在将其作为参数传递之前或通过添加自定义参数转换。
(Anorm doc表示类型安全问题,以及如何实现转换)
答案 2 :(得分:0)
getOrElse(null)
导致您的问题。这是因为您在getOrElse
上呼叫Option[Float]
。但是,Scala中的null
无法分配给Float
等值类型。来自scaladoc:
Null是所有引用类型的子类型;它唯一的例子是空引用。由于Null不是值类型的子类型,因此null不是任何此类型的成员。 例如,无法为scala.Int类型的变量指定null。
同一声明适用于Float
。由于null
和Float
没有共同的超类型(Any
除外),因此Scala将caller.map(_._1).getOrElse(null)
推断为Any
而不是Float
。这在Play 2.2.x中是允许的,但是在2.3.x中,Any
不再允许作为参数传递,因为它不是类型安全的。
解决方案?只需删除getOrElse(null)
即可,您就可以了。 caller.map(_._1)
是Option[Float]
,Anorm知道如何处理它是否为空。通常,在Scala中使用null
是不好的做法。如果你看到自己打电话给getOrElse(null)
,你应该问自己是否有更好的方法来安全地处理它。