关于 mysql:Slick flatMap 不会将所有查询作为一个组执行

 2022-01-07 

Slick flatMap does not execute all queries as a group

我发现 Scala Slick 不能像普通的 sql 一样执行多个查询。

例如:

1
2
3
4
5
6
val query = sql"""
  SET @referenceTime = '12:00:00';
  SELECT * FROM table WHERE dateTime <= @referenceTime;
"
"".as[ClassResult]

dbConfig.db.run(query)

在这个字符串中有 2 个查询,Slick 返回一个错误:

1
You have an error in your SQL syntax; check the manual .... to use near 'SELECT * FROM

由此,我了解到 "SELECT" 之前的所有查询(可能是最后一个查询)都将被忽略。所以,我找到了一个使用 flatMap 的解决方案,但不是完美的。

1
2
3
4
5
6
7
8
9
val timeQuery = sql"""SET @referenceTime = '12:00:00';""".as[String]
val dataQuery = sql"""SELECT * FROM table WHERE dateTime <= @referenceTime;""".as[ClassResult]

val composedAction = for {
  timeRes <- timeQuery,
  dataRes <- dataQuery
} yield dataRes

dbConfig.db.run(composedAction)

此运行在 99% 的情况下返回结果(项目列表)。但是,有时列表是空的,即使我确定必须返回一些数据)。所以,我认为 compositionAction 不会每次都等待并作为一个组执行两个查询。我该怎么做,因为我需要在第二个查询中第一个的结果(在第二个中用作参数)

编辑:
另一种解决方案是等待第一个查询的结果并将其用作第二个查询的参数。但这是一个很好的解决方案/实践吗?使用同步代码。

1
2
3
4
5
6
7
   val timeQuery = sql"""SELECT '12:00:00';""".as[String]    
   var defaultTime: String =""
   val tempResult = dbConfig.db.run(timeParameterQuery.head).map(res => defaultTime = res)
   Await.result(tempResult, Duration.Inf)

   val dataQuery = sql"""SELECT * FROM table WHERE dateTime <= $defaultTime;""".as[ClassResult]    
   dbConfig.db.run(dataQuery)

我想在 slick 中使用 SQL 变量是有问题的,可能是多个 db 上下文。您可以使用 \\'map\\' 链接查询,而不是等待结果。尝试这样的事情(未经测试)

1
2
3
4
   val timeQuery = sql"""SELECT '12:00:00';""".as[String]    
   dbConfig.db.run(timeQuery.head).flatMap{res =>
      dbConfig.db.run(sql"""SELECT * FROM table WHERE dateTime <= $res;""".as[ClassResult])
   }