迁移从2.2到2.3:Any没有隐式视图

时间:2015-02-18 12:19:18

标签: scala playframework playframework-2.2 playframework-2.3 anorm

尝试将我的项目从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),
                     ^

我该怎么做才能解决这个问题? 据我从文档中了解,我需要定义参数类型。但在下面的代码中,我无法理解在哪里以及如何做到这一点。

3 个答案:

答案 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类型

Source

答案 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。由于nullFloat没有共同的超类型(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),你应该问自己是否有更好的方法来安全地处理它。