Будущее и Вариант для понимания в пятно - PullRequest
0 голосов
/ 14 октября 2018

Я довольно новичок в использовании Slick, и теперь я столкнулся с проблемой, как извлечь некоторые данные из двух таблиц.У меня есть одна таблица

class ExecutionTable(tag: Tag) extends Table[ExecTuple](tag, "execution") {
  val id: Rep[String] = column[String]("id")
  val executionDefinitionId: Rep[Long] = column[Long]("executionDefinitionId")
  // other fields are omitted

  def * = ???
}

и другая таблица

class ServiceStatusTable(tag: Tag)
  extends Table[(String, Option[String])](tag, "serviceStatus") {
  def serviceId: Rep[String] = column[String]("serviceId")
  def detail: Rep[String] = column[String]("detail")

  def * = (serviceId, detail.?)
}

В Дао я преобразовываю данные из этих двух таблиц в бизнес-объект

case class ServiceStatus(
  id: String, 
  detail: Option[String] = None, //other fields
)

вот так

private lazy val getServiceStatusCompiled = Compiled {
  (id: Rep[String], tenantId: Rep[String]) =>
  for {
    exec   <- getExecutionById(id, tenantId)
    status <- serviceStatuses if exec.id === status.serviceId
  } yield mapToServiceStatus(exec, status)
}

и более поздних версий

def getServiceStatus(id: String, tenantId: String)
: Future[Option[ServiceStatus]] = db
  .run(getServiceStatusCompiled(id, tenantId).result.transactionally)
  .map(_.headOption)

Проблема заключается в том, что не для всех записей из таблицы execution существует запись в таблице serviceStatus.Я не могу изменить таблицу execution и добавить в нее поле details, так как оно относится только к конкретной услуге.Когда я запускаю запрос в случае, если для записи из execution существует запись в serviceStatus, все работает как положено.Но если в serviceStatus нет записи, Future [None] возвращается.Вопрос: есть ли возможность получить status in для понимания как Option, в зависимости от существующей записи в таблице serviceStatus или другого обходного пути?

1 Ответ

0 голосов
/ 16 октября 2018

Обычно, если условие соединения не находит соответствующую запись в «правой» таблице, но результат все равно должен содержать строку из «левой» таблицы, используется левое соединение.В вашем случае вы можете сделать что-то вроде:

Execution
  .filter(...execution table filter...)
  .joinLeft(ServiceStatus).on(_.id===_.serviceId)

Это даст вам пару

(Execution, Rep[Option[ServiceStatus]]) 

и после выполнения запроса:

(Execution, Option[ServiceStatus])      
...