У меня есть структура, которая имеет 2 отношения: компания и местоположение. Чтобы сохранить классификацию, мне нужно знать идентификаторы ее отношений, которые могут потребовать персистентности сущности сначала (то есть она может уже существовать в базе данных, иначе она должна быть вставлена).Slick 3.1.1: Вставьте объект со своими отношениями в одной транзакции
Идентификаторы - это UUID, назначенные приложением (то есть не автоинкрементные с помощью db), поэтому приложение назначает идентификатор, который либо окажется идентификатором объекта, либо будет заменен фактическим идентификатором в транзакции, если объект уже существует.
код, который делает это выглядит следующим образом:
def create(classified: Classified, company: Company, location: Location): Future[String] = {
val interaction = for {
comp <- companies.filter(_.name === company.name).result.headOption flatMap {
case None => companies returning companies.map(_.id) += company
case Some(comp) => DBIO.successful(comp.id.get)
}
loc <- locations.filter(_.name === location.name).result.headOption flatMap {
case None => locations returning locations.map(_.id) += location
case Some(loc) => DBIO.successful(loc.id.get)
}
cl <- classifieds returning classifieds.map(_.id) += classified.copy(companyId = comp, locationId = loc)
} yield cl
db.run(interaction.transactionally)
}
Вышеприведенные отлично работает, когда побежал против Postgres (который является производственной базой данных), но не для H2 (который является испытанием и dev database) с ошибкой: [SlickException: эта СУБД позволяет возвращать только один столбец AutoInc из INSERT]
Похоже, что драйвер H2 не возвращает идентификаторы, если они не являются разновидностями автоинкремента.
Итак, как эту транзакцию можно записать так, чтобы а) вставки произошли в одной транзакции б) с минимальными обратными переходами db и c) в нейтральной базе данных?
РЕДАКТИРОВАТЬ:
выше метод используется от контроллера следующим образом:
classifiedDao.create(
Classified(Some(UUID.randomUUID().toString), c.title, Jsoup.clean(c.body, Whitelist.basic()), c.refNo, "", ""),
Company(Some(UUID.randomUUID().toString), c.companyName, c.companyEmail, None, None),
Location(Some(UUID.randomUUID().toString), c.location, None)
).map(_ =>
Redirect(routes.Classifieds.form()).flashing("success" -> "Classified submitted")
)
Просто уточнить:. Есть '' company' и location' уже есть UUID, назначенный на вставке (строка 'случай None => компании возвращающиеся companies.map (_ ID) + = company')? – Roman
Да.Контроллер назначает идентификаторы всем трем объектам, а затем передает объекты в DAO, которые должны быть сохранены, если объект уже сохранен, идентификатор отбрасывается, а тот, который извлекается из db, используется отдельно от классифицированного, который всегда используется. – javito
@Roman этот комментарий был чистым гением. В случае «Нет» я уже знаю идентификатор, все, что мне нужно сделать, это выполнить результат с другими DBActions, и я закончен. Спасибо, это было блестяще. PS: Я отправляю ответ ниже для потомков. – javito