TL; DR:我想创建一个纯函数,它将返回在单个DBIOAction对象内关闭的一系列插入操作(例如def foo():DBIOAction)。当ID不是自动递增时,这是微不足道的,当ID由DB自动递增时,对我来说很难。
我现在已经使用Slick超过一周了,我真正喜欢它的是能够将操作序列作为DBIOAction关闭,可以由我的函数返回,之后可以应用于DB作为DB副作用。
当我将数据插入单个表时,这一切都很好。但是,如果在插入的第二行中必须使用一个插入行的ID(如任何1-many关系),我应该如何处理情况,因为ID是自动递增的?
想象一下,我们有CATEGORIES table
列:id, name, parent_id
,其中parent_id
为NULL或指向表格中的其他行。
如果ID没有自动递增,这是微不足道的:
def insert(cId: Int, cName: String, subcId: Int, subcName: String) =
DBIO.seq(
categories +=(subcId, subcName, None),
categories +=(cId, cName, Some(subcId))
)
但是当ID ARE自动增加时,这很棘手。 As stated in the documentation,我需要将returning
结合使用投影到需要返回的列,例如:
val categoryId =
(categories returning categories.map(_.id)) += (0, name, None)
现在我可以在插入第二行时使用返回的ID。真棒。但是,我如何关闭数据库操作的序列,因为我返回了ID,但不是动作本身?
def insert(cName: String, subcName: String): DBIOAction[Int, Stream, Write] = ???
答案 0 :(得分:1)
所以我会回答我自己的问题,因为有人可能会在我开始时发现它很奇怪。
val categoryId =
(categories returning categories.map(_.id)) += (0, name, None)
诀窍是categoryId
也是 DBIOAction ,而不是我原先预期的Int。琐碎,但你去了。
答案 1 :(得分:0)
我就是这样做的(我在我的一个项目中做过类似的事情):
def insert(cName: String, subcName: String) = {
for {
id <- (categories returning categories.map(_.id)) += (subcName, None)
_ <- categories +=(cName, Some(id))
} yield ()
然后我会调用函数:
db.run(insert(categoryName, subCategoryName))