slick 3.0 insertIfNotExists implementation based on non primary key

388 views Asked by At

I have table with autoInc primary key('id') but i need to control uniqueness of records in the table by another column as well (column 'code').

I tried to make it this way:

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)
  }
}

Methods findByCode and insert returns Future[A] and Future[Int] respectively. When i ran this code on some amount of records to be inserted i realised that findByCode doesnt find records which have been inserted and i got massive records duplication. As a workaround i built a constraint in my db (driven by postgres), but i would like to know if i'm doing smth wrong in the code or it is potentialy cannot be guarantee to check if record exists when i just was inserted in another concurrent transaction?

What can be the optimal recommended way for my purpose?

1) build uniqueness constraint and wrap insert int try block? (i use this now)

2) implement insertOrUpdate using plainsql with one query (insert into where not exists (select where ...))

3) write a synchronisation wrapper for such queries (with Await) and run them synchronously in one thread

4) smth else

Thanks in advance for any advices.

0

There are 0 answers