光滑:传入列进行更新

时间:2018-04-15 05:13:52

标签: sql database scala slick

假设我们有一个包含以下列的FoodTable:NameCaloriesCarbsProtein。我有Name = ChocolateCalories = 100Carbs = "10g"Protein = "2g"的条目。

我想知道是否有传递列名和新值的方法来更新。例如,我想要一个像

的方法
def updateFood(food, columnName, value):
     table.filter(_.name === food).map(x => x.columnName).update(value)

似乎Slick无法使用动态列?我想避免编写SQL查询,因为这可能导致代码中的安全漏洞或错误。有没有办法做到这一点?

我也不想传递整个对象来更新,因为理想情况下应该是:

我想将列X更新为值Y.我只需要传入对象的id,列和要更新的值。

1 个答案:

答案 0 :(得分:1)

  

我想知道是否可以传递列名和新值来更新

这取决于你想要什么"列名"成为。为了保持安全,我建议使用"列名称"是一个可以选择表中列的函数。

如此高的水平:

// Won't compile, but we'll fix that in a moment
def updateFood[V](food: Food, column: FoodTable => Rep[V], value: V): DBIO[Int] =
  foods.filter(_.name === food.name).map(column).update(value)

...我们这样称呼:

updateFood(choc, _.calories, 99)

注意"列名称"是从FoodTable到某个值V的列的函数。然后,您为V提供一个值,我们会进行正常更新。

问题在于Slick知道如何将某些类型的值(String,Int等)映射到SQL中,而不是任何类型的值。上面的代码不会被编译,因为V不受限制。

我们可以解决一下我在V上添加约束的问题,而且它大部分会起作用:

// Will compile, will work for basic types
def updateFood[V : slick.ast.BaseTypedType](food: Food, column: FoodTable => Rep[V], value: V): DBIO[Int] =
 foods.filter(_.name === food.name).map(column).update(value)

但是,如果您有自定义列映射,则它们不会匹配约束。我们需要再迈出一步,并在范围内有一个隐含的形状:

def updateFood[V](food: Food, column: FoodTable => Rep[V], value: V)(implicit shape: Shape[_ <: FlatShapeLevel, Rep[V], V, _]): DBIO[Int] =
 foods.filter(_.name === food.name).map(column).update(value)

我认为Shape是Slick中额外的抽象级别,高于Rep[V]。形状水平的机制&#34;其他细节不是我能解释的,因为我还没有理解它们! (有一个关于Slick设计的讨论称为&#34;提升嵌入中的多态记录类型&#34;你可以在http://slick.lightbend.com/docs/找到它)

最后一点:如果你真的希望列名是String或类似的东西,我建议将字符串模式匹配(或以某种方式验证)到FoodTable => Rep函数并使用在你的SQL中。这将变得棘手,因为您的值V必须与您要更新的列的类型相匹配。

脱离我的头顶,看起来像这样:

def tryUpdateFood(food: Food, columnName: String, value: String): DBIO[Int] =
 columnName match {
   case "calories" => updateFood(food, _.calories, value.toInt)
   case "carbs" => updateFood(food, _.carbs, value)
   // etc...
   case unknown => DBIO.failed(new Exception(s"Don't know how to update $unknown columns"))
}

我可以想象更好的错误处理,更安全或更智能的解析值,但概括上述可能有效。

有关处理动态问题的其他方法的提示,请查看#Slick数据库应用程序的模式#34; (也列于:http://slick.lightbend.com/docs/),在演示文稿结束时,有关于&#34;动态排序&#34;的部分。