У меня есть таблица с первичным autoInc key('id')
, но мне нужно контролировать уникальность записей в таблице и по другому столбцу (столбец «код»).
Я пытался сделать это так:
def findByCode(code: String): Future[Option[A]] =
try db.run(tableQuery.filter(_.code === code).result.headOption)
def insert(entity: A): Future[Int] =
try db.run(tableQuery += entity)
def insertIfNotExists(code: String, entity: A): Future[Int] = {
findByCode(code).flatMap {
case None => insert(entity)
case _ => Future(-1)
}
}
Методы findByCode
и вставка возвращают Future[A]
и Future[Int]
соответственно. Когда я запустил этот код для некоторого количества вставляемых записей, я понял, что findByCode
не находит записи, которые были вставлены, и я получил массовое дублирование записей. В качестве обходного пути я создал ограничение в своей базе данных (управляемое postgres), но я хотел бы знать, делаю ли я что-то неправильно в коде, или потенциально невозможно гарантировать, что запись существует, когда я только что был вставлен в еще одна параллельная транзакция?
Что может быть оптимальным рекомендуемым способом для моей цели?
1) построить ограничение уникальности и обернуть вставку в блоке try? (я использую это сейчас)
2) реализовать вставкуOrUpdate с помощью plainsql одним запросом (вставить туда, где не существует (выбрать, где...))
3) написать обертку синхронизации для таких запросов (с Await) и запускать их синхронно в одном потоке
4) что-то еще
Заранее спасибо за любые советы.
findByCode
, и до того, как вы вставили ее, будет создана дубликат. Если ваша проверка будет довольно медленной, шансы увеличатся. - person yǝsʞǝla   schedule 09.06.2015