Я хочу иметь метод getOrCreateFoobar(id)
, который либо получает уже существующий Foobar на id
, либо создает / вставляет новый Foobar с id
.Этот метод будет вызываться с высокой степенью одновременности, поэтому я должен сериализовать / синхронизировать доступ для этого атомарного метода get-or-create, чтобы не два одновременных запроса дважды создавали Foobar с одним и тем же идентификатором.
ПосколькуСущность может еще не существовать, пока нет ни одной строки, по которой я мог бы заблокировать синхронизацию.кроме того, блокировка всей таблицы также кажется плохой идеей - потенциальный рецепт тупиковой катастрофы (?)
Существует такой шаблон для создания искусственных объектов, таких как LockEntity
, которые могут иметь свойство типа Name
.Для каждого UseCase я предоставляю строку / экземпляр типа Name=GET_OR_CREATE_FOOBAR
.Который затем используется в репозитории с замком PESSIMISTIC_WRITE
:
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT e FROM LockEntity e WHERE name = :name")
LockEntity obtainLock(@Param("name") String name);
, который затем можно использовать как:
obtainLock("GET_OR_CREATE_FOOBAR")
// now we hold the lock and are synchronized
get()
if (doesNotExistYet) create()
commit / release-lock
Есть ли лучший / более легкий способ?