假设我们有一个包含以下列的FoodTable:Name
,Calories
,Carbs
,Protein
。我有Name = Chocolate
,Calories = 100
,Carbs = "10g"
和Protein = "2g"
的条目。
我想知道是否有传递列名和新值的方法来更新。例如,我想要一个像
的方法def updateFood(food, columnName, value):
table.filter(_.name === food).map(x => x.columnName).update(value)
似乎Slick无法使用动态列?我想避免编写SQL查询,因为这可能导致代码中的安全漏洞或错误。有没有办法做到这一点?
我也不想传递整个对象来更新,因为理想情况下应该是:
我想将列X更新为值Y.我只需要传入对象的id,列和要更新的值。
答案 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;的部分。