Scala编译失败,原因是:找不到参数W的隐式值



我得到了一个不想编译的doobie查询:

package de.x.vmdbplanningvalues.impl.queries
import de.x.campaignplans.CampaignPlanId
import de.x.distributionbrands.DistributionBrandId
import de.x.vmdbplanningvalues._
import doobie._
object UpdateVmdbPlanningValuesQuery {
case class VmdbPlanningUpdate(
creditRatingRejections: Option[Double],
goodsCoupons: Option[Double],
customerDiscounts: Option[Double],
campaignPlanId: String,
distributionBrandId: String,
country: String,
categoryId: String,
lane: VmdbLane
)
def apply(
distributionBrand: DistributionBrandId,
country: String,
campaignPlanId: CampaignPlanId,
category: String,
updates: List[VmdbPlanningValuesForVmdbLane]
): ConnectionIO[Unit] = {
for {
_ <- updateQuery(updates.map(update =>
VmdbPlanningUpdate(
update.creditRatingRejections,
update.goodsCoupons,
update.customerDiscounts,
campaignPlanId.id,
distributionBrand.id,
country,
category,
update.lane
)
))
} yield ()
}
def updateQuery[T: Write](updates: List[VmdbPlanningUpdate]): ConnectionIO[Int] = {
val sql =
"""
UPDATE vmdb_planning_values as vmdb
SET vmdb.credit_rating_rejections = ?,
vmdb.goods_coupons = ?,
vmdb.customer_discounts = ?
FROM campaign_plan cp
WHERE cp.id = ?
AND vmdb.distribution_brand_id = ?
AND vmdb.country_id = ?
AND vmdb.year=DATE_PART('year', cp.start_date)
AND vmdb.quarter=DATE_PART('quarter', cp.start_date)
AND vmdb.category_id = ?
AND vmdb.lane = ?
"""
Update[VmdbPlanningUpdate](sql).updateMany(updates)
}
}

然而,它失败了,并出现以下错误:

[error] /Users/johannesklauss/Documents/campaign-service/server/src/main/scala/de/x/vmdbplanningvalues/impl/queries/UpdateVmdbPlanningValuesQuery.scala:60:35: could not find implicit value for parameter W: doobie.Write[de.x.vmdbplanningvalues.impl.queries.UpdateVmdbPlanningValuesQuery.VmdbPlanningUpdate]
[error]     Update[VmdbPlanningUpdate](sql).updateMany(updates)
[error] 

我不太确定错误消息是什么意思,因为我对Scala中的隐词仍然有点模糊。有人有主意吗?

编辑:添加VmdbLane.scala:

package de.x.vmdbplanningvalues
import io.circe.Decoder.Result
import io.circe._
sealed trait VmdbLane {
override def toString: String = VmdbLane.toEnum(this)
}
object VmdbLane {
case object New extends VmdbLane
case object CarryOver extends VmdbLane
case object Sale extends VmdbLane
case object Sum extends VmdbLane
def toEnum(e: VmdbLane): String =
e match {
case New => "new"
case CarryOver => "carryOver"
case Sale => "sale"
case Sum => "sum"
}
def fromEnum(s: String): Option[VmdbLane] =
Option(s) collect {
case "new" => New
case "carryOver" => CarryOver
case "sale" => Sale
case "sum" => Sum
}
implicit val jsonFormat: Encoder[VmdbLane] with Decoder[VmdbLane] =
new Encoder[VmdbLane] with Decoder[VmdbLane] {
override def apply(a: VmdbLane): Json = Encoder.encodeString(toEnum(a))
override def apply(c: HCursor): Result[VmdbLane] =
c.value.asString.flatMap(s => fromEnum(s)) match {
case Some(a) => Right(a)
case None => Left(DecodingFailure("VmdbLane", c.history))
}
}
}

问题与Circe无关,而是与自定义doobie类型映射的工作方式有关。如果在VmdbLane对象中包含类似内容:

implicit val natGet: Get[VmdbLane] = Get[String].map(in => {
in match {
case "New"       => New
case "CarryOver" => CarryOver
case "Sale"      => Sale
case "Sum"       => Sum
}
})
implicit val natPut: Put[VmdbLane] = Put[String].contramap {
case New       => "New"
case CarryOver => "CarryOver"
case Sale      => "Sale"
case Sum       => "Sum"
}

编译器应该包括它应该工作的映射。

相关内容

最新更新